Skip to content
Permalink
Browse files

Merge pull request #665 from Oslandia/overview_centering

[2.1] Overview centering
  • Loading branch information
pcav committed Sep 5, 2013
2 parents 1aa5daf + 00041e6 commit 135ef365693f076a39269186e829f2590205b35e
@@ -300,7 +300,12 @@ class QgsComposerMap : QgsComposerItem
/**Sets flag if overview frame should be inverted
@note this function was added in version 1.9*/
void setOverviewInverted( bool inverted );
bool overviewInverted() const;
bool overviewInverted() const;

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

/**Sets mId to a number not yet used in the composition. mId is kept if it is not in use.
Usually, this function is called before adding the composer map to the composition*/
@@ -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() )
@@ -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()
@@ -591,6 +594,18 @@ void QgsComposerMapWidget::on_mOverviewInvertCheckbox_toggled( bool state )
}
}

void QgsComposerMapWidget::on_mOverviewCenterCheckbox_toggled( bool state )
{
if ( mComposerMap )
{
mComposerMap->setOverviewCentered( state );
}
mComposerMap->beginCommand( tr( "Overview centering mode changed" ) );
mComposerMap->cache();
mComposerMap->update();
mComposerMap->endCommand();
}

void QgsComposerMapWidget::on_mGridCheckBox_toggled( bool state )
{
if ( !mComposerMap )
@@ -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();
@@ -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 ),
@@ -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 ),
@@ -116,6 +118,26 @@ 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();

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;
@@ -297,6 +319,10 @@ void QgsComposerMap::paint( QPainter* painter, const QStyleOptionGraphicsItem* i

QgsRectangle requestRectangle;
requestedExtent( requestRectangle );

QgsRectangle cExtent;
extentCenteredOnOverview( cExtent );

double horizontalVScaleFactor = horizontalViewScaleFactor();
if ( horizontalVScaleFactor < 0 )
{
@@ -305,15 +331,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();

@@ -351,16 +377,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 );
@@ -757,6 +787,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 );
@@ -874,6 +907,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() )
{
@@ -1727,63 +1769,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
@@ -1836,6 +1885,12 @@ void QgsComposerMap::setOverviewInverted( bool inverted )
update();
}

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

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

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

QgsRenderContext context;
@@ -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 */
bool overviewCentered() const { return mOverviewCentered; }
/** Set the overview's centering mode */
void setOverviewCentered( bool centered );

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

@@ -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();
@@ -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
@@ -525,6 +535,11 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
void createDefaultOverviewFrameSymbol();
void createDefaultGridLineSymbol();
void initGridAnnotationFormatFromProject();

/**
* Returns the extent, centered on the overview frame
*/
void extentCenteredOnOverview( QgsRectangle& extent ) const;
};

#endif
@@ -54,9 +54,9 @@
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>438</width>
<height>1454</height>
<y>-376</y>
<width>439</width>
<height>1439</height>
</rect>
</property>
<property name="sizePolicy">
@@ -697,6 +697,13 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="mOverviewCenterCheckbox">
<property name="text">
<string>Center on overview</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

0 comments on commit 135ef36

Please sign in to comment.
You can’t perform that action at this time.