Skip to content

Commit

Permalink
[labeling] Fix some valid curved label placements are rejected
Browse files Browse the repository at this point in the history
because we fail to correctly determine character angles, and
instead reject the placement as violating the max character in/out
angles

This happens predominantly in maps with geographic CRS, but is
also seen in large scale projected maps. The calculation for
line circle intersections used to determine curved label character
placement becomes numerically unstable when the map extent width/height
is small.
  • Loading branch information
nyalldawson committed Apr 5, 2021
1 parent 9960b15 commit 79b00fd
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/core/pal/feature.cpp
Expand Up @@ -1405,10 +1405,12 @@ static std::unique_ptr< LabelPosition > _createCurvedCandidate( LabelPosition *l
std::size_t FeaturePart::createCurvedCandidatesAlongLine( std::vector< std::unique_ptr< LabelPosition > > &lPos, PointSet *mapShape, bool allowOverrun, Pal *pal )
{
LabelInfo *li = mLF->curvedLabelInfo();

// label info must be present
if ( !li )
return 0;

const int characterCount = li->count();
if ( !li || characterCount == 0 )
if ( characterCount == 0 )
return 0;

// TODO - we may need an explicit penalty for overhanging labels. Currently, they are penalized just because they
Expand Down
7 changes: 7 additions & 0 deletions src/core/pal/feature.h
Expand Up @@ -56,6 +56,13 @@ namespace pal
{
public:

/**
* 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
Expand Down
21 changes: 21 additions & 0 deletions src/core/pal/geomfunction.cpp
Expand Up @@ -378,6 +378,21 @@ void GeomFunction::findLineCircleIntersection( double cx, double cy, double radi
double x1, double y1, double x2, double y2,
double &xRes, double &yRes )
{
double multiplier = 1;
if ( radius < 10 )
{
// these calculations get unstable for small coordinates differences, e.g. as a result of map labeling in a geographic
// CRS
multiplier = 10000;
x1 *= multiplier;
y1 *= multiplier;
x2 *= multiplier;
y2 *= multiplier;
cx *= multiplier;
cy *= multiplier;
radius *= multiplier;
}

double dx = x2 - x1;
double dy = y2 - y1;

Expand Down Expand Up @@ -406,4 +421,10 @@ void GeomFunction::findLineCircleIntersection( double cx, double cy, double radi
xRes = x1 + t * dx;
yRes = y1 + t * dy;
}

if ( multiplier != 1 )
{
xRes /= multiplier;
yRes /= multiplier;
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 79b00fd

Please sign in to comment.