Skip to content

Commit

Permalink
[labeling] Move minium/maximum angle settings for curved labels out o…
Browse files Browse the repository at this point in the history
…f PAL
  • Loading branch information
nirvn authored and nyalldawson committed Apr 7, 2021
1 parent 5106d41 commit 700cee2
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 40 deletions.
4 changes: 3 additions & 1 deletion src/core/labeling/qgspallabeling.cpp
Expand Up @@ -2527,8 +2527,10 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext

// TODO: only for placement which needs character info
// account for any data defined font metrics adjustments
lf->setMaximumCharacterAngleInside( std::clamp( maxcharanglein, 20.0, 60.0 ) * M_PI / 180 );
lf->setMaximumCharacterAngleOutside( std::clamp( maxcharangleout, -95.0, -20.0 ) * M_PI / 180 );
lf->calculateInfo( placement == QgsPalLayerSettings::Curved || placement == QgsPalLayerSettings::PerimeterCurved,
labelFontMetrics.get(), xform, maxcharanglein, maxcharangleout, format().allowHtmlFormatting() ? &doc : nullptr );
labelFontMetrics.get(), xform, format().allowHtmlFormatting() ? &doc : nullptr );
// for labelFeature the LabelInfo is passed to feat when it is registered

// TODO: allow layer-wide feature dist in PAL...?
Expand Down
14 changes: 2 additions & 12 deletions src/core/labeling/qgstextlabelfeature.cpp
Expand Up @@ -54,7 +54,7 @@ bool QgsTextLabelFeature::hasCharacterFormat( int partId ) const
return partId < mCharacterFormats.size();
}

void QgsTextLabelFeature::calculateInfo( bool curvedLabeling, QFontMetricsF *fm, const QgsMapToPixel *xform, double maxinangle, double maxoutangle, QgsTextDocument *document )
void QgsTextLabelFeature::calculateInfo( bool curvedLabeling, QFontMetricsF *fm, const QgsMapToPixel *xform, QgsTextDocument *document )
{
if ( mInfo )
return;
Expand All @@ -64,16 +64,6 @@ void QgsTextLabelFeature::calculateInfo( bool curvedLabeling, QFontMetricsF *fm,
qreal letterSpacing = mDefinedFont.letterSpacing();
qreal wordSpacing = mDefinedFont.wordSpacing();

// max angle between curved label characters (20.0/-20.0 was default in QGIS <= 1.8)
if ( maxinangle < 20.0 )
maxinangle = 20.0;
if ( 60.0 < maxinangle )
maxinangle = 60.0;
if ( maxoutangle > -20.0 )
maxoutangle = -20.0;
if ( -95.0 > maxoutangle )
maxoutangle = -95.0;

// create label info!
const double mapScale = xform->mapUnitsPerPixel();
const double characterHeight = mapScale * fm->height();
Expand Down Expand Up @@ -133,7 +123,7 @@ void QgsTextLabelFeature::calculateInfo( bool curvedLabeling, QFontMetricsF *fm,

characterWidths[i] = mapScale * charWidth;
}
mInfo = new pal::LabelInfo( characterHeight, std::move( characterWidths ), maxinangle, maxoutangle );
mInfo = new pal::LabelInfo( characterHeight, std::move( characterWidths ) );
}

QgsTextDocument QgsTextLabelFeature::document() const
Expand Down
37 changes: 36 additions & 1 deletion src/core/labeling/qgstextlabelfeature.h
Expand Up @@ -63,7 +63,7 @@ class QgsTextLabelFeature : public QgsLabelFeature
bool hasCharacterFormat( int partId ) const;

//! calculate data for info(). setDefinedFont() must have been called already.
void calculateInfo( bool curvedLabeling, QFontMetricsF *fm, const QgsMapToPixel *xform, double maxinangle, double maxoutangle, QgsTextDocument *document = nullptr );
void calculateInfo( bool curvedLabeling, QFontMetricsF *fm, const QgsMapToPixel *xform, QgsTextDocument *document = nullptr );

//! Gets data-defined values
const QMap< QgsPalLayerSettings::Property, QVariant > &dataDefinedValues() const { return mDataDefinedValues; }
Expand Down Expand Up @@ -92,6 +92,38 @@ class QgsTextLabelFeature : public QgsLabelFeature
*/
void setDocument( const QgsTextDocument &document );

/**
* Sets the maximum \a angle (in radians) between inside curved label characters.
* \see maximumCharacterAngleInside()
* \see setMaximumCharacterAngleOutside()
* \since QGIS 3.20
*/
void setMaximumCharacterAngleInside( double angle ) { mMaximumCharacterAngleInside = angle; }

/**
* Returns the maximum angle (in radians) between inside curved label characters.
* \see setMaximumCharacterAngleInside()
* \see maximumCharacterAngleOutside()
* \since QGIS 3.20
*/
double maximumCharacterAngleInside() const { return mMaximumCharacterAngleInside; }

/**
* Sets the maximum \a angle (in radians) between outside curved label characters.
* \see maximumCharacterAngleOutside()
* \see setMaximumCharacterAngleInside()
* \since QGIS 3.20
*/
void setMaximumCharacterAngleOutside( double angle ) { mMaximumCharacterAngleOutside = angle; }

/**
* Returns the maximum angle (in radians) between outside curved label characters.
* \see setMaximumCharacterAngleOutside()
* \see maximumCharacterAngleInside()
* \since QGIS 3.20
*/
double maximumCharacterAngleOutside() const { return mMaximumCharacterAngleOutside; }

protected:
//! List of graphemes (used for curved labels)
QStringList mClusters;
Expand All @@ -107,6 +139,9 @@ class QgsTextLabelFeature : public QgsLabelFeature

QgsTextDocument mDocument;

double mMaximumCharacterAngleInside = 0;
double mMaximumCharacterAngleOutside = 0;

};

#endif //QGSTEXTLABELFEATURE_H
17 changes: 11 additions & 6 deletions src/core/pal/feature.cpp
Expand Up @@ -27,21 +27,24 @@
*
*/

#include "qgsgeometry.h"
#include "pal.h"
#include "layer.h"
#include "feature.h"
#include "geomfunction.h"
#include "labelposition.h"
#include "pointset.h"
#include "util.h"
#include "costcalculator.h"

#include "qgis.h"
#include "qgsgeometry.h"
#include "qgsgeos.h"
#include "qgstextlabelfeature.h"

This comment has been minimized.

Copy link
@PeterPetrik

PeterPetrik Apr 9, 2021

Contributor

@nirvn @nyalldawson this breaks today's nightly build. looks like you need some additional include here?

In file included from /Users/admin/qgis/builds/nightly/QGIS/src/core/pal/feature.cpp:42:
/Users/admin/qgis/builds/nightly/QGIS/src/core/labeling/qgstextlabelfeature.h:82:89: error: call to unavailable member function 'value': introduced in macOS 10.14
    QFontMetricsF *labelFontMetrics() { return mFontMetrics.has_value() ? &mFontMetrics.value() : nullptr; }
                                                                           ~~~~~~~~~~~~~^~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/optional:946:27: note: candidate function has been explicitly made unavailable
    constexpr value_type& value() &
                          ^

This comment has been minimized.

Copy link
@nyalldawson

nyalldawson Apr 9, 2021

Collaborator

Not sure sorry -- does it give any clue as to what you are supposed to use? It's a standard c++17 feature.

This comment has been minimized.

Copy link
@PeterPetrik

PeterPetrik Apr 9, 2021

Contributor

maybe missing #include < QFontMetricsF> in the feature.cpp file? not sure

This comment has been minimized.

Copy link
@jef-n

jef-n Apr 9, 2021

Member

Why did https://github.com/qgis/QGIS/runs/2284637998 succeed? What's the difference of the CI build to the "real" build? Is the mac nightly also too heavy for the CI like the windows nightly?

#include "qgsmessagelog.h"
#include "costcalculator.h"
#include "qgsgeometryutils.h"
#include "qgslabeling.h"
#include "qgspolygon.h"

#include <QLinkedList>
#include <cmath>
#include <cfloat>
Expand Down Expand Up @@ -1310,6 +1313,8 @@ std::unique_ptr< LabelPosition > FeaturePart::curvedPlacementAtOffset( PointSet
double angle = std::atan2( -dy, dx );

const int characterCount = li->count();
const double maximumCharacterAngleInside = qgis::down_cast< QgsTextLabelFeature *>( mLF )->maximumCharacterAngleInside();
const double maximumCharacterAngleOutside = qgis::down_cast< QgsTextLabelFeature *>( mLF )->maximumCharacterAngleOutside();
for ( int i = 0; i < characterCount; i++ )
{
double last_character_angle = angle;
Expand Down Expand Up @@ -1338,10 +1343,10 @@ std::unique_ptr< LabelPosition > FeaturePart::curvedPlacementAtOffset( PointSet
angleDelta -= 2 * M_PI;
while ( angleDelta < -M_PI )
angleDelta += 2 * M_PI;
if ( applyAngleConstraints && ( ( li->maxCharAngleInsideRadians > 0 && angleDelta > 0
&& angleDelta > li->maxCharAngleInsideRadians )
|| ( li->maxCharAngleOutsideRadians < 0 && angleDelta < 0
&& angleDelta < li->maxCharAngleOutsideRadians ) ) )
if ( applyAngleConstraints && ( ( maximumCharacterAngleInside > 0 && angleDelta > 0
&& angleDelta > maximumCharacterAngleInside )
|| ( maximumCharacterAngleOutside < 0 && angleDelta < 0
&& angleDelta < maximumCharacterAngleOutside ) ) )
{
return nullptr;
}
Expand Down
23 changes: 3 additions & 20 deletions src/core/pal/feature.h
Expand Up @@ -60,14 +60,9 @@ namespace pal
* Constructor for LabelInfo
* \param characterHeight height of characters
* \param characterWidths vector of character widths
* \param maxinangle maximum acceptable in angle (in degrees)
* \param maxoutangle maximum acceptable out angle (in degrees)
*/
LabelInfo( double characterHeight, std::vector< double > characterWidths, double maxinangle = 20.0, double maxoutangle = -20.0 )
: maxCharAngleInsideRadians( maxinangle * M_PI / 180 )
// outside angle should be negative
, maxCharAngleOutsideRadians( ( maxoutangle > 0 ? -maxoutangle : maxoutangle ) * M_PI / 180 )
, characterHeight( characterHeight )
*/
LabelInfo( double characterHeight, std::vector< double > characterWidths )
: characterHeight( characterHeight )
, mCharacterWidths( characterWidths )
{
}
Expand All @@ -77,18 +72,6 @@ namespace pal
//! LabelInfo cannot be copied
LabelInfo &operator=( const LabelInfo &rh ) = delete;

/**
* Maximum angle between inside curved label characters (in radians).
* \see maxCharAngleOutsideRadians
*/
double maxCharAngleInsideRadians = 0;

/**
* Maximum angle between outside curved label characters (in radians).
* \see maxCharAngleInsideRadians
*/
double maxCharAngleOutsideRadians = 0;

// TODO - maybe individual character height would give better results!

/**
Expand Down

0 comments on commit 700cee2

Please sign in to comment.