Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add autocentering of overview
Work funded by Tuscany Region - SITA. Contract "Support to the use
of GFOSS (Geographic Free and Open Source Software) Desktop tools"
(CIG Z3B06FA6D7).
  • Loading branch information
Hugo Mercier committed Jun 17, 2013
1 parent bdd61d5 commit 1556185
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 34 deletions.
11 changes: 11 additions & 0 deletions src/app/composer/qgscomposermapwidget.cpp
Expand Up @@ -303,6 +303,8 @@ void QgsComposerMapWidget::updateGuiElements()
mOverviewBlendModeComboBox->setBlendMode( mComposerMap->overviewBlendMode() );
//overview inverted
mOverviewInvertCheckbox->setChecked( mComposerMap->overviewInverted() );
//center overview
mOverviewCenterCheckbox->setChecked( mComposerMap->overviewCentered() );

//grid
if ( mComposerMap->gridEnabled() )
Expand Down Expand Up @@ -452,6 +454,7 @@ void QgsComposerMapWidget::blockAllSignals( bool b )
mOverviewFrameStyleButton->blockSignals( b );
mOverviewBlendModeComboBox->blockSignals( b );
mOverviewInvertCheckbox->blockSignals( b );
mOverviewCenterCheckbox->blockSignals( b );
}

void QgsComposerMapWidget::on_mUpdatePreviewButton_clicked()
Expand Down Expand Up @@ -591,6 +594,14 @@ void QgsComposerMapWidget::on_mOverviewInvertCheckbox_toggled( bool state )
}
}

void QgsComposerMapWidget::on_mOverviewCenterCheckbox_toggled( bool state )
{
if ( mComposerMap )
{
mComposerMap->setOverviewCentered( state );
}
}

void QgsComposerMapWidget::on_mGridCheckBox_toggled( bool state )
{
if ( !mComposerMap )
Expand Down
1 change: 1 addition & 0 deletions src/app/composer/qgscomposermapwidget.h
Expand Up @@ -46,6 +46,7 @@ class QgsComposerMapWidget: public QWidget, private Ui::QgsComposerMapWidgetBase
void on_mOverviewFrameStyleButton_clicked();
void on_mOverviewBlendModeComboBox_currentIndexChanged( int index );
void on_mOverviewInvertCheckbox_toggled( bool state );
void on_mOverviewCenterCheckbox_toggled( bool state );

void on_mXMinLineEdit_editingFinished();
void on_mXMaxLineEdit_editingFinished();
Expand Down
126 changes: 92 additions & 34 deletions src/core/composer/qgscomposermap.cpp
Expand Up @@ -41,7 +41,8 @@

QgsComposerMap::QgsComposerMap( QgsComposition *composition, int x, int y, int width, int height )
: QgsComposerItem( x, y, width, height, composition ), mKeepLayerSet( false ),
mOverviewFrameMapId( -1 ), mOverviewBlendMode( QPainter::CompositionMode_SourceOver ), mOverviewInverted( false ), mGridEnabled( false ), mGridStyle( Solid ),
mOverviewFrameMapId( -1 ), mOverviewBlendMode( QPainter::CompositionMode_SourceOver ), mOverviewInverted( false ), mOverviewCentered( false ),
mGridEnabled( false ), mGridStyle( Solid ),
mGridIntervalX( 0.0 ), mGridIntervalY( 0.0 ), mGridOffsetX( 0.0 ), mGridOffsetY( 0.0 ), mGridAnnotationFontColor( QColor( 0, 0, 0 ) ),
mGridAnnotationPrecision( 3 ), mShowGridAnnotation( false ), mGridBlendMode( QPainter::CompositionMode_SourceOver ),
mLeftGridAnnotationPosition( OutsideMapFrame ), mRightGridAnnotationPosition( OutsideMapFrame ),
Expand Down Expand Up @@ -86,7 +87,8 @@ QgsComposerMap::QgsComposerMap( QgsComposition *composition, int x, int y, int w

QgsComposerMap::QgsComposerMap( QgsComposition *composition )
: QgsComposerItem( 0, 0, 10, 10, composition ), mKeepLayerSet( false ), mOverviewFrameMapId( -1 ),
mOverviewBlendMode( QPainter::CompositionMode_SourceOver ), mOverviewInverted( false ), mGridEnabled( false ), mGridStyle( Solid ),
mOverviewBlendMode( QPainter::CompositionMode_SourceOver ), mOverviewInverted( false ), mOverviewCentered( false ),
mGridEnabled( false ), mGridStyle( Solid ),
mGridIntervalX( 0.0 ), mGridIntervalY( 0.0 ), mGridOffsetX( 0.0 ), mGridOffsetY( 0.0 ), mGridAnnotationFontColor( QColor( 0, 0, 0 ) ),
mGridAnnotationPrecision( 3 ), mShowGridAnnotation( false ), mGridBlendMode( QPainter::CompositionMode_SourceOver ),
mLeftGridAnnotationPosition( OutsideMapFrame ), mRightGridAnnotationPosition( OutsideMapFrame ),
Expand Down Expand Up @@ -116,6 +118,28 @@ QgsComposerMap::QgsComposerMap( QgsComposition *composition )
initGridAnnotationFormatFromProject();
}

void QgsComposerMap::extentCenteredOnOverview( QgsRectangle& extent ) const
{
extent = mExtent;
if ( ! mOverviewCentered ) {
return;
}

if ( mOverviewFrameMapId != -1 ) {
const QgsComposerMap* overviewFrameMap = mComposition->getComposerMapById( mOverviewFrameMapId );
QgsRectangle otherExtent = overviewFrameMap->extent();

if ( ! mExtent.contains( otherExtent ) ) {
QgsPoint center = otherExtent.center();
QgsRectangle movedExtent( center.x() - mExtent.width() / 2,
center.y() - mExtent.height() / 2,
center.x() - mExtent.width() / 2 + mExtent.width(),
center.y() - mExtent.height() / 2 + mExtent.height() );
extent = movedExtent;
}
}
}

QgsComposerMap::~QgsComposerMap()
{
delete mOverviewFrameMapSymbol;
Expand Down Expand Up @@ -297,6 +321,10 @@ void QgsComposerMap::paint( QPainter* painter, const QStyleOptionGraphicsItem* i

QgsRectangle requestRectangle;
requestedExtent( requestRectangle );

QgsRectangle cExtent;
extentCenteredOnOverview( cExtent );

double horizontalVScaleFactor = horizontalViewScaleFactor();
if ( horizontalVScaleFactor < 0 )
{
Expand All @@ -305,15 +333,15 @@ void QgsComposerMap::paint( QPainter* painter, const QStyleOptionGraphicsItem* i

double imagePixelWidth = mExtent.width() / requestRectangle.width() * mCacheImage.width() ; //how many pixels of the image are for the map extent?
double scale = rect().width() / imagePixelWidth;
QgsPoint rotationPoint = QgsPoint(( mExtent.xMaximum() + mExtent.xMinimum() ) / 2.0, ( mExtent.yMaximum() + mExtent.yMinimum() ) / 2.0 );
QgsPoint rotationPoint = QgsPoint(( cExtent.xMaximum() + cExtent.xMinimum() ) / 2.0, ( cExtent.yMaximum() + cExtent.yMinimum() ) / 2.0 );

//shift such that rotation point is at 0/0 point in the coordinate system
double yShiftMM = ( requestRectangle.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
double xShiftMM = ( requestRectangle.xMinimum() - rotationPoint.x() ) * mapUnitsToMM();

//shift such that top left point of the extent at point 0/0 in item coordinate system
double xTopLeftShift = ( rotationPoint.x() - mExtent.xMinimum() ) * mapUnitsToMM();
double yTopLeftShift = ( mExtent.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
double xTopLeftShift = ( rotationPoint.x() - cExtent.xMinimum() ) * mapUnitsToMM();
double yTopLeftShift = ( cExtent.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();

painter->save();

Expand Down Expand Up @@ -351,16 +379,20 @@ void QgsComposerMap::paint( QPainter* painter, const QStyleOptionGraphicsItem* i
QgsRectangle requestRectangle;
requestedExtent( requestRectangle );

QgsRectangle cExtent;
extentCenteredOnOverview( cExtent );

QSizeF theSize( requestRectangle.width() * mapUnitsToMM(), requestRectangle.height() * mapUnitsToMM() );
QgsPoint rotationPoint = QgsPoint(( mExtent.xMaximum() + mExtent.xMinimum() ) / 2.0, ( mExtent.yMaximum() + mExtent.yMinimum() ) / 2.0 );

QgsPoint rotationPoint = QgsPoint(( cExtent.xMaximum() + cExtent.xMinimum() ) / 2.0, ( cExtent.yMaximum() + cExtent.yMinimum() ) / 2.0 );

//shift such that rotation point is at 0/0 point in the coordinate system
double yShiftMM = ( requestRectangle.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
double xShiftMM = ( requestRectangle.xMinimum() - rotationPoint.x() ) * mapUnitsToMM();

//shift such that top left point of the extent at point 0/0 in item coordinate system
double xTopLeftShift = ( rotationPoint.x() - mExtent.xMinimum() ) * mapUnitsToMM();
double yTopLeftShift = ( mExtent.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
double xTopLeftShift = ( rotationPoint.x() - cExtent.xMinimum() ) * mapUnitsToMM();
double yTopLeftShift = ( cExtent.yMaximum() - rotationPoint.y() ) * mapUnitsToMM();
painter->save();
painter->translate( mXOffset, mYOffset );
painter->translate( xTopLeftShift, yTopLeftShift );
Expand Down Expand Up @@ -757,6 +789,9 @@ bool QgsComposerMap::writeXML( QDomElement& elem, QDomDocument & doc ) const
{
overviewFrameElem.setAttribute( "overviewInverted", "false" );
}

overviewFrameElem.setAttribute( "overviewCentered", mOverviewCentered ? "true" : "false" );

QDomElement overviewFrameStyleElem = QgsSymbolLayerV2Utils::saveSymbol( QString(), mOverviewFrameMapSymbol, doc );
overviewFrameElem.appendChild( overviewFrameStyleElem );
composerMapElem.appendChild( overviewFrameElem );
Expand Down Expand Up @@ -874,6 +909,15 @@ bool QgsComposerMap::readXML( const QDomElement& itemElem, const QDomDocument& d
setOverviewInverted( false );
}

if ( overviewFrameElem.attribute( "overviewCentered" ).compare( "true", Qt::CaseInsensitive ) == 0 )
{
setOverviewCentered( true );
}
else
{
setOverviewCentered( false );
}

QDomElement overviewFrameSymbolElem = overviewFrameElem.firstChildElement( "symbol" );
if ( !overviewFrameSymbolElem.isNull() )
{
Expand Down Expand Up @@ -1727,63 +1771,70 @@ double QgsComposerMap::maxExtension() const
return maxExtension + mAnnotationFrameDistance + gridFrameDist;
}

void QgsComposerMap::mapPolygon( QPolygonF& poly ) const
void QgsComposerMap::mapPolygon( const QgsRectangle& extent, QPolygonF& poly ) const
{
poly.clear();
if ( mRotation == 0 )
{
poly << QPointF( mExtent.xMinimum(), mExtent.yMaximum() );
poly << QPointF( mExtent.xMaximum(), mExtent.yMaximum() );
poly << QPointF( mExtent.xMaximum(), mExtent.yMinimum() );
poly << QPointF( mExtent.xMinimum(), mExtent.yMinimum() );
poly << QPointF( extent.xMinimum(), extent.yMaximum() );
poly << QPointF( extent.xMaximum(), extent.yMaximum() );
poly << QPointF( extent.xMaximum(), extent.yMinimum() );
poly << QPointF( extent.xMinimum(), extent.yMinimum() );
return;
}

//there is rotation
QgsPoint rotationPoint(( mExtent.xMaximum() + mExtent.xMinimum() ) / 2.0, ( mExtent.yMaximum() + mExtent.yMinimum() ) / 2.0 );
QgsPoint rotationPoint(( extent.xMaximum() + extent.xMinimum() ) / 2.0, ( extent.yMaximum() + extent.yMinimum() ) / 2.0 );
double dx, dy; //x-, y- shift from rotation point to corner point

//top left point
dx = rotationPoint.x() - mExtent.xMinimum();
dy = rotationPoint.y() - mExtent.yMaximum();
dx = rotationPoint.x() - extent.xMinimum();
dy = rotationPoint.y() - extent.yMaximum();
rotate( mRotation, dx, dy );
poly << QPointF( rotationPoint.x() + dx, rotationPoint.y() + dy );

//top right point
dx = rotationPoint.x() - mExtent.xMaximum();
dy = rotationPoint.y() - mExtent.yMaximum();
dx = rotationPoint.x() - extent.xMaximum();
dy = rotationPoint.y() - extent.yMaximum();
rotate( mRotation, dx, dy );
poly << QPointF( rotationPoint.x() + dx, rotationPoint.y() + dy );

//bottom right point
dx = rotationPoint.x() - mExtent.xMaximum();
dy = rotationPoint.y() - mExtent.yMinimum();
dx = rotationPoint.x() - extent.xMaximum();
dy = rotationPoint.y() - extent.yMinimum();
rotate( mRotation, dx, dy );
poly << QPointF( rotationPoint.x() + dx, rotationPoint.y() + dy );

//bottom left point
dx = rotationPoint.x() - mExtent.xMinimum();
dy = rotationPoint.y() - mExtent.yMinimum();
dx = rotationPoint.x() - extent.xMinimum();
dy = rotationPoint.y() - extent.yMinimum();
rotate( mRotation, dx, dy );
poly << QPointF( rotationPoint.x() + dx, rotationPoint.y() + dy );
}

void QgsComposerMap::mapPolygon( QPolygonF& poly ) const
{
return mapPolygon( mExtent, poly );
}

void QgsComposerMap::requestedExtent( QgsRectangle& extent ) const
{
QgsRectangle newExtent;
extentCenteredOnOverview( newExtent );
if ( mRotation == 0 )
{
extent = mExtent;
return;
extent = newExtent;
}
else
{
QPolygonF poly;
mapPolygon( newExtent, poly );
QRectF bRect = poly.boundingRect();
extent.setXMinimum( bRect.left() );
extent.setXMaximum( bRect.right() );
extent.setYMinimum( bRect.top() );
extent.setYMaximum( bRect.bottom() );
}

QPolygonF poly;
mapPolygon( poly );
QRectF bRect = poly.boundingRect();
extent.setXMinimum( bRect.left() );
extent.setXMaximum( bRect.right() );
extent.setYMinimum( bRect.top() );
extent.setYMaximum( bRect.bottom() );
return;
}

double QgsComposerMap::mapUnitsToMM() const
Expand Down Expand Up @@ -1836,6 +1887,12 @@ void QgsComposerMap::setOverviewInverted( bool inverted )
update();
}

void QgsComposerMap::setOverviewCentered( bool centered )
{
mOverviewCentered = centered;
update();
}

void QgsComposerMap::setGridLineSymbol( QgsLineSymbolV2* symbol )
{
delete mGridLineSymbol;
Expand Down Expand Up @@ -2165,7 +2222,8 @@ void QgsComposerMap::drawOverviewMapExtent( QPainter* p )
}

QgsRectangle otherExtent = overviewFrameMap->extent();
QgsRectangle thisExtent = extent();
QgsRectangle thisExtent;
extentCenteredOnOverview( thisExtent );
QgsRectangle intersectRect = thisExtent.intersect( &otherExtent );

QgsRenderContext context;
Expand Down
15 changes: 15 additions & 0 deletions src/core/composer/qgscomposermap.h
Expand Up @@ -332,6 +332,11 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
/** Sets the overview's inversion mode*/
void setOverviewInverted( bool inverted );

/** Returns true if the extent is forced to center on the overview when the overview is outside the extent */
bool overviewCentered() const { return mOverviewCentered; }
/** Set the overview's centering mode */
void setOverviewCentered( bool centered );

void setGridLineSymbol( QgsLineSymbolV2* symbol );
QgsLineSymbolV2* gridLineSymbol() { return mGridLineSymbol; }

Expand Down Expand Up @@ -408,6 +413,8 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
/**Blend mode for overview*/
QPainter::CompositionMode mOverviewBlendMode;
bool mOverviewInverted;
/** Centering mode for overview */
bool mOverviewCentered;

/**Establishes signal/slot connection for update in case of layer change*/
void connectUpdateSlot();
Expand Down Expand Up @@ -503,6 +510,9 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
@param poly out: the result polygon with the four corner points. The points are clockwise, starting at the top-left point
@return true in case of success*/
void mapPolygon( QPolygonF& poly ) const;
/** mapPolygon variant using a given extent */
void mapPolygon( const QgsRectangle& extent, QPolygonF& poly ) const;

/**Calculates the extent to request and the yShift of the top-left point in case of rotation.*/
void requestedExtent( QgsRectangle& extent ) const;
/**Scales a composer map shift (in MM) and rotates it by mRotation
Expand All @@ -525,6 +535,11 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
void createDefaultOverviewFrameSymbol();
void createDefaultGridLineSymbol();
void initGridAnnotationFormatFromProject();

/**
* Returns the extent, centered on the overview frame, if needed (when the overview frame is not visible)
*/
void extentCenteredOnOverview( QgsRectangle& extent ) const;
};

#endif
7 changes: 7 additions & 0 deletions src/ui/qgscomposermapwidgetbase.ui
Expand Up @@ -697,6 +697,13 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="mOverviewCenterCheckbox">
<property name="text">
<string>Center on overview when needed</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down

0 comments on commit 1556185

Please sign in to comment.