mirror of
https://github.com/qgis/QGIS.git
synced 2025-03-06 00:05:02 -05:00
Fix priority of parallel placements
Ensure that above line placement is preferred when both above and below line placements are valid
This commit is contained in:
parent
6eaaf92662
commit
04c51db551
@ -772,27 +772,29 @@ int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList<LabelPosit
|
||||
bool aboveLine = ( !reversed && ( flags & FLAG_ABOVE_LINE ) ) || ( reversed && ( flags & FLAG_BELOW_LINE ) );
|
||||
bool belowLine = ( !reversed && ( flags & FLAG_BELOW_LINE ) ) || ( reversed && ( flags & FLAG_ABOVE_LINE ) );
|
||||
|
||||
double placementCost = 0.0;
|
||||
if ( belowLine )
|
||||
{
|
||||
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - std::cos( beta ) * ( distanceLineToLabel + labelHeight ), candidateStartY - std::sin( beta ) * ( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle ) )
|
||||
{
|
||||
lPos.append( new LabelPosition( i, candidateStartX - std::cos( beta ) * ( distanceLineToLabel + labelHeight ), candidateStartY - std::sin( beta ) * ( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, cost + placementCost, this, isRightToLeft ) ); // Line
|
||||
placementCost += 0.001;
|
||||
const double candidateCost = cost + ( reversed ? 0 : 0.001 );
|
||||
lPos.append( new LabelPosition( i, candidateStartX - std::cos( beta ) * ( distanceLineToLabel + labelHeight ), candidateStartY - std::sin( beta ) * ( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
}
|
||||
}
|
||||
if ( aboveLine )
|
||||
{
|
||||
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX + std::cos( beta ) *distanceLineToLabel, candidateStartY + std::sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle ) )
|
||||
{
|
||||
lPos.append( new LabelPosition( i, candidateStartX + std::cos( beta ) *distanceLineToLabel, candidateStartY + std::sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, cost + placementCost, this, isRightToLeft ) ); // Line
|
||||
placementCost += 0.001;
|
||||
const double candidateCost = cost + ( !reversed ? 0 : 0.001 ); // no extra cost for above line placements
|
||||
lPos.append( new LabelPosition( i, candidateStartX + std::cos( beta ) *distanceLineToLabel, candidateStartY + std::sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
}
|
||||
}
|
||||
if ( flags & FLAG_ON_LINE )
|
||||
{
|
||||
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - labelHeight * std::cos( beta ) / 2, candidateStartY - labelHeight * std::sin( beta ) / 2, labelWidth, labelHeight, angle ) )
|
||||
lPos.append( new LabelPosition( i, candidateStartX - labelHeight * std::cos( beta ) / 2, candidateStartY - labelHeight * std::sin( beta ) / 2, labelWidth, labelHeight, angle, cost + placementCost, this, isRightToLeft ) ); // Line
|
||||
{
|
||||
const double candidateCost = cost + 0.002;
|
||||
lPos.append( new LabelPosition( i, candidateStartX - labelHeight * std::cos( beta ) / 2, candidateStartY - labelHeight * std::sin( beta ) / 2, labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Horizontal )
|
||||
@ -925,17 +927,26 @@ int FeaturePart::createCandidatesAlongLineNearMidpoint( QList<LabelPosition *> &
|
||||
if ( aboveLine )
|
||||
{
|
||||
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX + std::cos( beta ) *distanceLineToLabel, candidateStartY + std::sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle ) )
|
||||
positions.append( new LabelPosition( i, candidateStartX + std::cos( beta ) *distanceLineToLabel, candidateStartY + std::sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, cost, this, isRightToLeft ) ); // Line
|
||||
{
|
||||
const double candidateCost = cost + ( !reversed ? 0 : 0.001 ); // no extra cost for above line placements
|
||||
positions.append( new LabelPosition( i, candidateStartX + std::cos( beta ) *distanceLineToLabel, candidateStartY + std::sin( beta ) *distanceLineToLabel, labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
}
|
||||
}
|
||||
if ( belowLine )
|
||||
{
|
||||
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - std::cos( beta ) * ( distanceLineToLabel + labelHeight ), candidateStartY - std::sin( beta ) * ( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle ) )
|
||||
positions.append( new LabelPosition( i, candidateStartX - std::cos( beta ) * ( distanceLineToLabel + labelHeight ), candidateStartY - std::sin( beta ) * ( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, cost, this, isRightToLeft ) ); // Line
|
||||
{
|
||||
const double candidateCost = cost + ( !reversed ? 0.001 : 0 );
|
||||
positions.append( new LabelPosition( i, candidateStartX - std::cos( beta ) * ( distanceLineToLabel + labelHeight ), candidateStartY - std::sin( beta ) * ( distanceLineToLabel + labelHeight ), labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
}
|
||||
}
|
||||
if ( flags & FLAG_ON_LINE )
|
||||
{
|
||||
if ( !mLF->permissibleZonePrepared() || GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), candidateStartX - labelHeight * std::cos( beta ) / 2, candidateStartY - labelHeight * std::sin( beta ) / 2, labelWidth, labelHeight, angle ) )
|
||||
positions.append( new LabelPosition( i, candidateStartX - labelHeight * std::cos( beta ) / 2, candidateStartY - labelHeight * std::sin( beta ) / 2, labelWidth, labelHeight, angle, cost, this, isRightToLeft ) ); // Line
|
||||
{
|
||||
const double candidateCost = cost + 0.002;
|
||||
positions.append( new LabelPosition( i, candidateStartX - labelHeight * std::cos( beta ) / 2, candidateStartY - labelHeight * std::sin( beta ) / 2, labelWidth, labelHeight, angle, candidateCost, this, isRightToLeft ) ); // Line
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Horizontal )
|
||||
|
@ -58,6 +58,7 @@ class TestQgsLabelingEngine : public QObject
|
||||
void testCurvedLabelsWithTinySegments();
|
||||
void testCurvedLabelCorrectLinePlacement();
|
||||
void testCurvedLabelNegativeDistance();
|
||||
void testParallelPlacementPreferAbove();
|
||||
void testLabelBoundary();
|
||||
void testLabelBlockingRegion();
|
||||
void testLabelRotationWithReprojection();
|
||||
@ -1158,6 +1159,58 @@ void TestQgsLabelingEngine::testCurvedLabelNegativeDistance()
|
||||
QVERIFY( imageCheck( QStringLiteral( "label_curved_negative_distance" ), img, 20 ) );
|
||||
}
|
||||
|
||||
void TestQgsLabelingEngine::testParallelPlacementPreferAbove()
|
||||
{
|
||||
// given the choice of above or below placement, labels should always be placed above
|
||||
QgsPalLayerSettings settings;
|
||||
setDefaultLabelParams( settings );
|
||||
|
||||
QgsTextFormat format = settings.format();
|
||||
format.setSize( 20 );
|
||||
format.setColor( QColor( 0, 0, 0 ) );
|
||||
settings.setFormat( format );
|
||||
|
||||
settings.fieldName = QStringLiteral( "'XXXXXXXX'" );
|
||||
settings.isExpression = true;
|
||||
settings.placement = QgsPalLayerSettings::Line;
|
||||
settings.placementFlags = QgsPalLayerSettings::AboveLine | QgsPalLayerSettings::BelowLine | QgsPalLayerSettings::MapOrientation;
|
||||
settings.labelPerPart = false;
|
||||
|
||||
std::unique_ptr< QgsVectorLayer> vl2( new QgsVectorLayer( QStringLiteral( "LineString?crs=epsg:3946&field=id:integer" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) );
|
||||
vl2->setRenderer( new QgsNullSymbolRenderer() );
|
||||
|
||||
QgsFeature f;
|
||||
f.setAttributes( QgsAttributes() << 1 );
|
||||
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "LineString (190000 5000010, 190200 5000000)" ) ) );
|
||||
QVERIFY( vl2->dataProvider()->addFeature( f ) );
|
||||
|
||||
vl2->setLabeling( new QgsVectorLayerSimpleLabeling( settings ) ); // TODO: this should not be necessary!
|
||||
vl2->setLabelsEnabled( true );
|
||||
|
||||
// make a fake render context
|
||||
QSize size( 640, 480 );
|
||||
QgsMapSettings mapSettings;
|
||||
mapSettings.setDestinationCrs( vl2->crs() );
|
||||
|
||||
mapSettings.setOutputSize( size );
|
||||
mapSettings.setExtent( f.geometry().boundingBox() );
|
||||
mapSettings.setLayers( QList<QgsMapLayer *>() << vl2.get() );
|
||||
mapSettings.setOutputDpi( 96 );
|
||||
|
||||
QgsLabelingEngineSettings engineSettings = mapSettings.labelingEngineSettings();
|
||||
engineSettings.setFlag( QgsLabelingEngineSettings::UsePartialCandidates, false );
|
||||
engineSettings.setFlag( QgsLabelingEngineSettings::DrawLabelRectOnly, true );
|
||||
//engineSettings.setFlag( QgsLabelingEngineSettings::DrawCandidates, true );
|
||||
mapSettings.setLabelingEngineSettings( engineSettings );
|
||||
|
||||
QgsMapRendererSequentialJob job( mapSettings );
|
||||
job.start();
|
||||
job.waitForFinished();
|
||||
|
||||
QImage img = job.renderedImage();
|
||||
QVERIFY( imageCheck( QStringLiteral( "parallel_prefer_above" ), img, 20 ) );
|
||||
}
|
||||
|
||||
void TestQgsLabelingEngine::testLabelBoundary()
|
||||
{
|
||||
// test that no labels are drawn outside of the specified label boundary
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Loading…
x
Reference in New Issue
Block a user