Skip to content

Commit

Permalink
[composer] Correctly handle symbology using map units when drawing gr…
Browse files Browse the repository at this point in the history
…id lines and overlays on maps (fix #8210)
  • Loading branch information
nyalldawson committed Jun 17, 2014
1 parent 95f88ae commit 4a70d1b
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 27 deletions.
78 changes: 52 additions & 26 deletions src/core/composer/qgscomposermap.cpp
Expand Up @@ -1432,21 +1432,45 @@ void QgsComposerMap::drawGrid( QPainter* p )
QRectF thisPaintRect = QRectF( 0, 0, QGraphicsRectItem::rect().width(), QGraphicsRectItem::rect().height() );
p->setClipRect( thisPaintRect );

QPaintDevice* thePaintDevice = p->device();
if ( !thePaintDevice )
{
return;
}

// set the blend mode for drawing grid lines
p->save();
p->setCompositionMode( mGridBlendMode );
p->setRenderHint( QPainter::Antialiasing );

//setup painter scaling to dots so that raster symbology is drawn to scale
double dotsPerMM = thePaintDevice->logicalDpiX() / 25.4;
p->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots

//setup render context
QgsMapSettings ms = mComposition->mapSettings();
//context units should be in dots
ms.setOutputSize( QSizeF( rect().width() * dotsPerMM, rect().height() * dotsPerMM ).toSize() );
ms.setExtent( *currentMapExtent() );
ms.setOutputDpi( p->device()->logicalDpiX() );
QgsRenderContext context = QgsRenderContext::fromMapSettings( ms );
context.setPainter( p );

//simpler approach: draw vertical lines first, then horizontal ones
if ( mGridStyle == QgsComposerMap::Solid )
{
//need to scale line to dots, rather then mm, since the painter has been scaled to dots
QLineF line;
for ( ; vIt != verticalLines.constEnd(); ++vIt )
{
drawGridLine( vIt->second, p );
line = QLineF( vIt->second.p1() * dotsPerMM, vIt->second.p2() * dotsPerMM ) ;
drawGridLine( line, context );
}

for ( ; hIt != horizontalLines.constEnd(); ++hIt )
{
drawGridLine( hIt->second, p );
line = QLineF( hIt->second.p1() * dotsPerMM, hIt->second.p2() * dotsPerMM ) ;
drawGridLine( line, context );
}
}
else //cross
Expand All @@ -1456,7 +1480,7 @@ void QgsComposerMap::drawGrid( QPainter* p )
{
//start mark
crossEnd1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( vIt->second.p1(), vIt->second.p2(), mCrossLength );
drawGridLine( QLineF( vIt->second.p1(), crossEnd1 ), p );
drawGridLine( QLineF( vIt->second.p1(), crossEnd1 ), context );

//test for intersection with every horizontal line
hIt = horizontalLines.constBegin();
Expand All @@ -1466,20 +1490,20 @@ void QgsComposerMap::drawGrid( QPainter* p )
{
crossEnd1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( intersectionPoint, vIt->second.p1(), mCrossLength );
crossEnd2 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( intersectionPoint, vIt->second.p2(), mCrossLength );
drawGridLine( QLineF( crossEnd1, crossEnd2 ), p );
drawGridLine( QLineF( crossEnd1, crossEnd2 ), context );
}
}
//end mark
QPointF crossEnd2 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( vIt->second.p2(), vIt->second.p1(), mCrossLength );
drawGridLine( QLineF( vIt->second.p2(), crossEnd2 ), p );
drawGridLine( QLineF( vIt->second.p2(), crossEnd2 ), context );
}

hIt = horizontalLines.constBegin();
for ( ; hIt != horizontalLines.constEnd(); ++hIt )
{
//start mark
crossEnd1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( hIt->second.p1(), hIt->second.p2(), mCrossLength );
drawGridLine( QLineF( hIt->second.p1(), crossEnd1 ), p );
drawGridLine( QLineF( hIt->second.p1(), crossEnd1 ), context );

vIt = verticalLines.constBegin();
for ( ; vIt != verticalLines.constEnd(); ++vIt )
Expand All @@ -1488,12 +1512,12 @@ void QgsComposerMap::drawGrid( QPainter* p )
{
crossEnd1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( intersectionPoint, hIt->second.p1(), mCrossLength );
crossEnd2 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( intersectionPoint, hIt->second.p2(), mCrossLength );
drawGridLine( QLineF( crossEnd1, crossEnd2 ), p );
drawGridLine( QLineF( crossEnd1, crossEnd2 ), context );
}
}
//end mark
crossEnd1 = QgsSymbolLayerV2Utils::pointOnLineWithDistance( hIt->second.p2(), hIt->second.p1(), mCrossLength );
drawGridLine( QLineF( hIt->second.p2(), crossEnd1 ), p );
drawGridLine( QLineF( hIt->second.p2(), crossEnd1 ), context );
}
}
// reset composition mode
Expand Down Expand Up @@ -1529,25 +1553,16 @@ void QgsComposerMap::drawGridFrame( QPainter* p, const QList< QPair< double, QLi
drawGridFrameBorder( p, bottomGridFrame, QgsComposerMap::Bottom );
}

void QgsComposerMap::drawGridLine( const QLineF& line, QPainter* p )
void QgsComposerMap::drawGridLine( const QLineF& line, QgsRenderContext& context )
{
if ( !mGridLineSymbol || !p )
if ( !mGridLineSymbol )
{
return;
}

//setup render context
QgsRenderContext context;
context.setPainter( p );
if ( mPreviewMode == Rectangle )
{
return;
}
else
{
context.setScaleFactor( 1.0 );
context.setRasterScaleFactor( mComposition->printResolution() / 25.4 );
}

QPolygonF poly;
poly << line.p1() << line.p2();
Expand Down Expand Up @@ -2556,22 +2571,33 @@ void QgsComposerMap::drawOverviewMapExtent( QPainter* p )
QgsRectangle thisExtent = *currentMapExtent();
QgsRectangle intersectRect = thisExtent.intersect( &otherExtent );

QgsRenderContext context;
//setup painter scaling to dots so that raster symbology is drawn to scale
double dotsPerMM = p->device()->logicalDpiX() / 25.4;

//setup render context
QgsMapSettings ms = mComposition->mapSettings();
//context units should be in dots
ms.setOutputSize( QSizeF( rect().width() * dotsPerMM, rect().height() * dotsPerMM ).toSize() );
ms.setExtent( *currentMapExtent() );
ms.setOutputDpi( p->device()->logicalDpiX() );
QgsRenderContext context = QgsRenderContext::fromMapSettings( ms );
context.setPainter( p );
context.setScaleFactor( 1.0 );
context.setRasterScaleFactor( mComposition->printResolution() / 25.4 );

p->save();
p->setCompositionMode( mOverviewBlendMode );
p->translate( mXOffset, mYOffset );
p->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
p->setRenderHint( QPainter::Antialiasing );

mOverviewFrameMapSymbol->startRender( context );

//construct a polygon corresponding to the intersecting map extent
//need to scale line to dots, rather then mm, since the painter has been scaled to dots
QPolygonF intersectPolygon;
double x = ( intersectRect.xMinimum() - thisExtent.xMinimum() ) / thisExtent.width() * rect().width();
double y = ( thisExtent.yMaximum() - intersectRect.yMaximum() ) / thisExtent.height() * rect().height();
double width = intersectRect.width() / thisExtent.width() * rect().width();
double height = intersectRect.height() / thisExtent.height() * rect().height();
double x = dotsPerMM * ( intersectRect.xMinimum() - thisExtent.xMinimum() ) / thisExtent.width() * rect().width();
double y = dotsPerMM * ( thisExtent.yMaximum() - intersectRect.yMaximum() ) / thisExtent.height() * rect().height();
double width = dotsPerMM * intersectRect.width() / thisExtent.width() * rect().width();
double height = dotsPerMM * intersectRect.height() / thisExtent.height() * rect().height();
intersectPolygon << QPointF( x, y ) << QPointF( x + width, y ) << QPointF( x + width, y + height ) << QPointF( x, y + height ) << QPointF( x, y );

QList<QPolygonF> rings; //empty list
Expand Down
2 changes: 1 addition & 1 deletion src/core/composer/qgscomposermap.h
Expand Up @@ -727,7 +727,7 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
void sortGridLinesOnBorders( const QList< QPair< double, QLineF > >& hLines, const QList< QPair< double, QLineF > >& vLines, QMap< double, double >& leftFrameEntries,
QMap< double, double >& rightFrameEntries, QMap< double, double >& topFrameEntries, QMap< double, double >& bottomFrameEntries ) const;
void drawGridFrameBorder( QPainter* p, const QMap< double, double >& borderPos, Border border );
void drawGridLine( const QLineF& line, QPainter* p );
void drawGridLine( const QLineF& line, QgsRenderContext& context );
void drawOverviewMapExtent( QPainter* p );
void createDefaultOverviewFrameSymbol();
void createDefaultGridLineSymbol();
Expand Down

0 comments on commit 4a70d1b

Please sign in to comment.