Skip to content

Commit 34d5f5a

Browse files
committed
[pal] Also prefer above -> below for parallel line placement
(cherry-picked from 3b940fb)
1 parent 02b3fb8 commit 34d5f5a

File tree

2 files changed

+26
-19
lines changed

2 files changed

+26
-19
lines changed

src/core/pal/feature.cpp

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList<LabelPosit
616616
double *y = line->y;
617617

618618
// closed line? if so, we need to handle the final node angle
619-
bool closedLine = qgsDoubleNear( x[0], x[ numberNodes - 1]) && qgsDoubleNear( y[0], y[numberNodes - 1 ]);
619+
bool closedLine = qgsDoubleNear( x[0], x[ numberNodes - 1] ) && qgsDoubleNear( y[0], y[numberNodes - 1 ] );
620620
for ( int i = 1; i <= numberNodes - ( closedLine ? 1 : 2 ); ++i )
621621
{
622622
double x1 = x[i-1];
@@ -625,16 +625,16 @@ int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList<LabelPosit
625625
double y1 = y[i-1];
626626
double y2 = y[i];
627627
double y3 = y[ i == numberNodes - 1 ? 1 : i+1]; // wraparound for closed linestrings
628-
if ( qgsDoubleNear( y2, y3 ) && qgsDoubleNear( x2, x3))
628+
if ( qgsDoubleNear( y2, y3 ) && qgsDoubleNear( x2, x3 ) )
629629
continue;
630-
if ( qgsDoubleNear( y1, y2 ) && qgsDoubleNear( x1, x2))
630+
if ( qgsDoubleNear( y1, y2 ) && qgsDoubleNear( x1, x2 ) )
631631
continue;
632-
double vertexAngle = M_PI - ( atan2(y3 - y2, x3-x2) - atan2(y2 - y1, x2-x1) );
633-
vertexAngle = QgsGeometryUtils::normalizedAngle( vertexAngle );
632+
double vertexAngle = M_PI - ( atan2( y3 - y2, x3 - x2 ) - atan2( y2 - y1, x2 - x1 ) );
633+
vertexAngle = QgsGeometryUtils::normalizedAngle( vertexAngle );
634634

635-
// extreme angles form more than 45 degree angle at a node - these are the ones we don't want labels to cross
636-
if ( vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0 )
637-
extremeAngleNodes << i;
635+
// extreme angles form more than 45 degree angle at a node - these are the ones we don't want labels to cross
636+
if ( vertexAngle < M_PI * 135.0 / 180.0 || vertexAngle > M_PI * 225.0 / 180.0 )
637+
extremeAngleNodes << i;
638638
}
639639
extremeAngleNodes << numberNodes - 1;
640640

@@ -719,7 +719,7 @@ int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList<LabelPosit
719719

720720
//calculate some cost penalties
721721
double segmentCost = 1.0 - ( distanceToEndOfSegment - distanceToStartOfSegment ) / longestSegmentLength; // 0 -> 1 (lower for longer segments)
722-
double segmentAngleCost = 1-qAbs(fmod( currentSegmentAngle, M_PI )-M_PI_2)/M_PI_2; // 0 -> 1, lower for more horizontal segments
722+
double segmentAngleCost = 1 - qAbs( fmod( currentSegmentAngle, M_PI ) - M_PI_2 ) / M_PI_2; // 0 -> 1, lower for more horizontal segments
723723

724724
while ( currentDistanceAlongLine + labelWidth < distanceToEndOfSegment )
725725
{
@@ -764,20 +764,27 @@ int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList<LabelPosit
764764
bool aboveLine = ( !reversed && ( flags & FLAG_ABOVE_LINE ) ) || ( reversed && ( flags & FLAG_BELOW_LINE ) );
765765
bool belowLine = ( !reversed && ( flags & FLAG_BELOW_LINE ) ) || ( reversed && ( flags & FLAG_ABOVE_LINE ) );
766766

767-
if ( aboveLine )
768-
{
769-
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX + cos( beta ) *distanceLineToLabel, candidateStartY + sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle ) )
770-
lPos.append( new LabelPosition( i, candidateStartX + cos( beta ) *distanceLineToLabel, candidateStartY + sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, cost, this, isRightToLeft ) ); // Line
771-
}
767+
double placementCost = 0.0;
772768
if ( belowLine )
773769
{
774770
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - cos( beta ) *( distanceLineToLabel + labelHeight ), candidateStartY - sin( beta ) *( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle ) )
775-
lPos.append( new LabelPosition( i, candidateStartX - cos( beta ) *( distanceLineToLabel + labelHeight ), candidateStartY - sin( beta ) *( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, cost, this, isRightToLeft ) ); // Line
771+
{
772+
lPos.append( new LabelPosition( i, candidateStartX - cos( beta ) *( distanceLineToLabel + labelHeight ), candidateStartY - sin( beta ) *( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, cost + placementCost, this, isRightToLeft ) ); // Line
773+
placementCost += 0.001;
774+
}
775+
}
776+
if ( aboveLine )
777+
{
778+
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX + cos( beta ) *distanceLineToLabel, candidateStartY + sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle ) )
779+
{
780+
lPos.append( new LabelPosition( i, candidateStartX + cos( beta ) *distanceLineToLabel, candidateStartY + sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, cost + placementCost, this, isRightToLeft ) ); // Line
781+
placementCost += 0.001;
782+
}
776783
}
777784
if ( flags & FLAG_ON_LINE )
778785
{
779786
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - labelHeight*cos( beta ) / 2, candidateStartY - labelHeight*sin( beta ) / 2, labelWidth, labelHeight, angle ) )
780-
lPos.append( new LabelPosition( i, candidateStartX - labelHeight*cos( beta ) / 2, candidateStartY - labelHeight*sin( beta ) / 2, labelWidth, labelHeight, angle, cost, this, isRightToLeft ) ); // Line
787+
lPos.append( new LabelPosition( i, candidateStartX - labelHeight*cos( beta ) / 2, candidateStartY - labelHeight*sin( beta ) / 2, labelWidth, labelHeight, angle, cost + placementCost, this, isRightToLeft ) ); // Line
781788
}
782789
}
783790
else if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Horizontal )
@@ -863,7 +870,7 @@ int FeaturePart::createCandidatesAlongLineNearMidpoint( QList<LabelPosition*>& l
863870
{
864871
// label is bigger than line, use whole available line
865872
candidateLength = sqrt(( x[nbPoints-1] - x[0] ) * ( x[nbPoints-1] - x[0] )
866-
+ ( y[nbPoints-1] - y[0] ) * ( y[nbPoints-1] - y[0] ) );
873+
+ ( y[nbPoints-1] - y[0] ) * ( y[nbPoints-1] - y[0] ) );
867874
}
868875
else
869876
{

tests/src/python/test_qgspallabeling_placement.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ def test_prefer_line_above_instead_of_online(self):
370370
self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
371371
self.lyr.placement = QgsPalLayerSettings.Line
372372
self.lyr.placementFlags = QgsPalLayerSettings.AboveLine | QgsPalLayerSettings.OnLine | QgsPalLayerSettings.MapOrientation
373-
#self.checkTest()
373+
self.checkTest()
374374
self.removeMapLayer(self.layer)
375375
self.layer = None
376376

@@ -381,7 +381,7 @@ def test_prefer_line_below_instead_of_online(self):
381381
self._TestMapSettings = self.cloneMapSettings(self._MapSettings)
382382
self.lyr.placement = QgsPalLayerSettings.Line
383383
self.lyr.placementFlags = QgsPalLayerSettings.BelowLine | QgsPalLayerSettings.OnLine | QgsPalLayerSettings.MapOrientation
384-
#self.checkTest()
384+
self.checkTest()
385385
self.removeMapLayer(self.layer)
386386
self.layer = None
387387

0 commit comments

Comments
 (0)