Skip to content

Commit

Permalink
Inverted polygon renderer: fix rendering when projection is enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
Hugo Mercier committed May 26, 2014
1 parent 230c050 commit 315b28c
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 45 deletions.
66 changes: 26 additions & 40 deletions src/core/symbology-ng/qgsinvertedpolygonrenderer.cpp
Expand Up @@ -63,7 +63,6 @@ void QgsInvertedPolygonRenderer::startRender( QgsRenderContext& context, const Q
return; return;
} }


mSubRenderer->startRender( context, fields );
mFeaturesCategoryMap.clear(); mFeaturesCategoryMap.clear();
mFeatureDecorations.clear(); mFeatureDecorations.clear();
mFields = fields; mFields = fields;
Expand All @@ -81,28 +80,36 @@ void QgsInvertedPolygonRenderer::startRender( QgsRenderContext& context, const Q
// convert viewport to dest CRS // convert viewport to dest CRS
QRect e( context.painter()->viewport() ); QRect e( context.painter()->viewport() );
// add some space to hide borders and tend to infinity // add some space to hide borders and tend to infinity
e.adjust( -e.width()*10, -e.height()*10, e.width()*10, e.height()*10 ); e.adjust( -e.width()*5, -e.height()*5, e.width()*5, e.height()*5 );
QgsPolyline exteriorRing; QgsPolyline exteriorRing;
exteriorRing << mtp.toMapCoordinates( e.topLeft() ); exteriorRing << mtp.toMapCoordinates( e.topLeft() );
exteriorRing << mtp.toMapCoordinates( e.topRight() ); exteriorRing << mtp.toMapCoordinates( e.topRight() );
exteriorRing << mtp.toMapCoordinates( e.bottomRight() ); exteriorRing << mtp.toMapCoordinates( e.bottomRight() );
exteriorRing << mtp.toMapCoordinates( e.bottomLeft() ); exteriorRing << mtp.toMapCoordinates( e.bottomLeft() );
exteriorRing << mtp.toMapCoordinates( e.topLeft() ); exteriorRing << mtp.toMapCoordinates( e.topLeft() );


mTransform = context.coordinateTransform(); // copy the rendering context
mContext = context;

// If reprojection is enabled, we must reproject during renderFeature // If reprojection is enabled, we must reproject during renderFeature
// and act as if there is no reprojection // and act as if there is no reprojection
// If we don't do that, there is no need to have a simple rectangular extent // If we don't do that, there is no need to have a simple rectangular extent
// that covers the whole screen // that covers the whole screen
// (a rectangle in the destCRS cannot be expressed as valid coordinates in the sourceCRS in general) // (a rectangle in the destCRS cannot be expressed as valid coordinates in the sourceCRS in general)
if (mTransform) if ( context.coordinateTransform() )
{ {
// disable projection // disable projection
context.setCoordinateTransform(0); mContext.setCoordinateTransform(0);
// recompute extent so that polygon clipping is correct
QRect v( context.painter()->viewport() );
mContext.setExtent( QgsRectangle( mtp.toMapCoordinates( v.topLeft() ), mtp.toMapCoordinates( v.bottomRight() ) ) );
// do we have to recompute the MapToPixel ?
} }


mExtentPolygon.clear(); mExtentPolygon.clear();
mExtentPolygon.append(exteriorRing); mExtentPolygon.append(exteriorRing);

mSubRenderer->startRender( mContext, fields );
} }


bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker ) bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker )
Expand Down Expand Up @@ -173,6 +180,13 @@ bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature& feature, QgsRenderCo
{ {
return false; return false;
} }

const QgsCoordinateTransform* xform = context.coordinateTransform();
if ( xform )
{
geom->transform( *xform );
}

if ( (geom->wkbType() == QGis::WKBPolygon) || if ( (geom->wkbType() == QGis::WKBPolygon) ||
(geom->wkbType() == QGis::WKBPolygon25D) ) { (geom->wkbType() == QGis::WKBPolygon25D) ) {
multi.append(geom->asPolygon() ); multi.append(geom->asPolygon() );
Expand Down Expand Up @@ -215,34 +229,12 @@ bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature& feature, QgsRenderCo


for ( int i = 0; i < multi.size(); i++ ) { for ( int i = 0; i < multi.size(); i++ ) {
// add the exterior ring as interior ring to the first polygon // add the exterior ring as interior ring to the first polygon
if ( mTransform ) { cFeat.multiPolygon[0].append( multi[i][0] );
QgsPolyline new_ls;
QgsPolyline& old_ls = multi[i][0];
for ( int k = 0; k < old_ls.size(); k++ ) {
new_ls.append( mTransform->transform( old_ls[k] ) );
}
cFeat.multiPolygon[0].append( new_ls );
}
else
{
cFeat.multiPolygon[0].append( multi[i][0] );
}
// add interior rings as new polygons // add interior rings as new polygons
for ( int j = 1; j < multi[i].size(); j++ ) { for ( int j = 1; j < multi[i].size(); j++ ) {
QgsPolygon new_poly; QgsPolygon new_poly;
if ( mTransform ) { new_poly.append( multi[i][j] );
QgsPolyline new_ls;
QgsPolyline& old_ls = multi[i][j];
for ( int k = 0; k < old_ls.size(); k++ ) {
new_ls.append( mTransform->transform( old_ls[k] ) );
}
new_poly.append( new_ls );
}
else
{
new_poly.append( multi[i][j] );
}

cFeat.multiPolygon.append( new_poly ); cFeat.multiPolygon.append( new_poly );
} }
} }
Expand Down Expand Up @@ -281,7 +273,7 @@ void QgsInvertedPolygonRenderer::stopRender( QgsRenderContext& context )
} }
} }
} }
mSubRenderer->renderFeature( feat, context ); mSubRenderer->renderFeature( feat, mContext );
} }


// when no features are visible, we still have to draw the exterior rectangle // when no features are visible, we still have to draw the exterior rectangle
Expand All @@ -293,22 +285,16 @@ void QgsInvertedPolygonRenderer::stopRender( QgsRenderContext& context )
// empty feature with default attributes // empty feature with default attributes
QgsFeature feat( mFields ); QgsFeature feat( mFields );
feat.setGeometry( QgsGeometry::fromPolygon( mExtentPolygon ) ); feat.setGeometry( QgsGeometry::fromPolygon( mExtentPolygon ) );
mSubRenderer->renderFeature( feat, context ); mSubRenderer->renderFeature( feat, mContext );
} }


// draw feature decorations // draw feature decorations
foreach (FeatureDecoration deco, mFeatureDecorations ) foreach (FeatureDecoration deco, mFeatureDecorations )
{ {
mSubRenderer->renderFeature( deco.feature, context, deco.layer, deco.selected, deco.drawMarkers ); mSubRenderer->renderFeature( deco.feature, mContext, deco.layer, deco.selected, deco.drawMarkers );
} }


mSubRenderer->stopRender( context ); mSubRenderer->stopRender( mContext );

if ( mTransform )
{
// restore the coordinate transform if needed
context.setCoordinateTransform( mTransform );
}
} }


QString QgsInvertedPolygonRenderer::dump() const QString QgsInvertedPolygonRenderer::dump() const
Expand Down
4 changes: 2 additions & 2 deletions src/core/symbology-ng/qgsinvertedpolygonrenderer.h
Expand Up @@ -139,8 +139,8 @@ class CORE_EXPORT QgsInvertedPolygonRenderer : public QgsFeatureRendererV2
/** the polygon used as exterior ring that covers the current extent */ /** the polygon used as exterior ring that covers the current extent */
QgsPolygon mExtentPolygon; QgsPolygon mExtentPolygon;


/** the current coordinate transform (or null) */ /** the context used for rendering */
const QgsCoordinateTransform* mTransform; QgsRenderContext mContext;


/** fields of each feature*/ /** fields of each feature*/
QgsFields mFields; QgsFields mFields;
Expand Down
27 changes: 24 additions & 3 deletions tests/src/core/testqgsinvertedpolygonrenderer.cpp
Expand Up @@ -48,11 +48,12 @@ class TestQgsInvertedPolygon: public QObject
void singleSubRenderer(); void singleSubRenderer();
void graduatedSubRenderer(); void graduatedSubRenderer();
void preprocess(); void preprocess();
void projectionTest();


private: private:
bool mTestHasError; bool mTestHasError;
bool setQml( QString qmlFile ); bool setQml( QString qmlFile );
bool imageCheck( QString theType ); bool imageCheck( QString theType, const QgsRectangle* = 0 );
QgsMapSettings mMapSettings; QgsMapSettings mMapSettings;
QgsVectorLayer * mpPolysLayer; QgsVectorLayer * mpPolysLayer;
QString mTestDataDir; QString mTestDataDir;
Expand Down Expand Up @@ -124,6 +125,19 @@ void TestQgsInvertedPolygon::preprocess()
QVERIFY( imageCheck( "inverted_polys_preprocess" ) ); QVERIFY( imageCheck( "inverted_polys_preprocess" ) );
} }


//-8639421,8382691 : -3969110,12570905
void TestQgsInvertedPolygon::projectionTest()
{
// FIXME will have to find some overlapping polygons
mReport += "<h2>Inverted polygon renderer, projection test</h2>\n";
mMapSettings.setDestinationCrs( QgsCoordinateReferenceSystem("EPSG:2154") );
mMapSettings.setCrsTransformEnabled( true );
QgsRectangle extent( QgsPoint(-8639421,8382691), QgsPoint(-3969110,12570905) );
QVERIFY( setQml( "inverted_polys_single.qml" ) );
QVERIFY( imageCheck( "inverted_polys_projection", &extent ) );
mMapSettings.setCrsTransformEnabled( false );
}

// //
// Private helper functions not called directly by CTest // Private helper functions not called directly by CTest
// //
Expand All @@ -144,11 +158,18 @@ bool TestQgsInvertedPolygon::setQml( QString qmlFile )
return myStyleFlag; return myStyleFlag;
} }


bool TestQgsInvertedPolygon::imageCheck( QString theTestType ) bool TestQgsInvertedPolygon::imageCheck( QString theTestType, const QgsRectangle* extent )
{ {
//use the QgsRenderChecker test utility class to //use the QgsRenderChecker test utility class to
//ensure the rendered output matches our control image //ensure the rendered output matches our control image
mMapSettings.setExtent( mpPolysLayer->extent() ); if ( !extent )
{
mMapSettings.setExtent( mpPolysLayer->extent() );
}
else
{
mMapSettings.setExtent( *extent );
}
QgsRenderChecker myChecker; QgsRenderChecker myChecker;
myChecker.setControlName( "expected_" + theTestType ); myChecker.setControlName( "expected_" + theTestType );
myChecker.setMapSettings( mMapSettings ); myChecker.setMapSettings( mMapSettings );
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 315b28c

Please sign in to comment.