From 128727dc9839de58206410a0a68b7ec5f6c1eca3 Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Wed, 18 Dec 2013 02:27:58 +0100 Subject: [PATCH 01/24] #8725-R: define UseRenderingOptimization Redefine RenderingPrintComposition to UseRenderingOptimization --- src/core/composer/qgscomposermap.cpp | 2 +- src/core/qgsrendercontext.cpp | 2 +- src/core/qgsrendercontext.h | 10 +++++----- src/core/qgsvectorlayer.cpp | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/core/composer/qgscomposermap.cpp b/src/core/composer/qgscomposermap.cpp index 092f505e421f..e49cb38b56e2 100644 --- a/src/core/composer/qgscomposermap.cpp +++ b/src/core/composer/qgscomposermap.cpp @@ -208,7 +208,7 @@ void QgsComposerMap::draw( QPainter *painter, const QgsRectangle& extent, const mComposition->plotStyle() == QgsComposition::Postscript ) { //if outputing composer, disable optimisations like layer simplification - theRendererContext->setRenderingPrintComposition( true ); + theRendererContext->setUseRenderingOptimization( false ); } // force vector output (no caching of marker images etc.) diff --git a/src/core/qgsrendercontext.cpp b/src/core/qgsrendercontext.cpp index 75976a639064..d96bfcd28e0a 100644 --- a/src/core/qgsrendercontext.cpp +++ b/src/core/qgsrendercontext.cpp @@ -29,7 +29,7 @@ QgsRenderContext::QgsRenderContext() mRasterScaleFactor( 1.0 ), mRendererScale( 1.0 ), mLabelingEngine( NULL ), - mRenderingPrintComposition( false ) + mUseRenderingOptimization( true ) { } diff --git a/src/core/qgsrendercontext.h b/src/core/qgsrendercontext.h index c4b4fce6af52..01d96baab551 100644 --- a/src/core/qgsrendercontext.h +++ b/src/core/qgsrendercontext.h @@ -95,9 +95,9 @@ class CORE_EXPORT QgsRenderContext //! Added in QGIS v2.0 void setSelectionColor( const QColor& color ) { mSelectionColor = color; } - /**True if the rendering request comes from a print composition, false it comes from a normal window request */ - void setRenderingPrintComposition( bool renderingPrintComposition ) { mRenderingPrintComposition = renderingPrintComposition; } - bool renderingPrintComposition( ) const { return mRenderingPrintComposition; } + /**Returns true if the rendering optimization (geometry simplification) can be executed*/ + bool useRenderingOptimization() const { return mUseRenderingOptimization; } + void setUseRenderingOptimization( bool enabled ) { mUseRenderingOptimization = enabled; } private: @@ -138,8 +138,8 @@ class CORE_EXPORT QgsRenderContext /** Color used for features that are marked as selected */ QColor mSelectionColor; - /**True if the rendering request comes from a print composition, false it comes from a normal window request */ - bool mRenderingPrintComposition; + /**True if the rendering optimization (geometry simplification) can be executed*/ + bool mUseRenderingOptimization; }; #endif diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index b7bd5f5841ca..e8854f24a495 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -705,7 +705,7 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext ) QgsFeatureIterator fit = QgsFeatureIterator(); // Enable the simplification of the geometries (Using the current map2pixel context) before fetch the features. - if ( simplifyDrawingCanbeApplied( QgsVectorLayer::GeometrySimplification | QgsVectorLayer::EnvelopeSimplification ) && !( featureRequest.flags() & QgsFeatureRequest::NoGeometry ) && !rendererContext.renderingPrintComposition() ) + if ( simplifyDrawingCanbeApplied( QgsVectorLayer::GeometrySimplification | QgsVectorLayer::EnvelopeSimplification ) && !( featureRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { QPainter* p = rendererContext.painter(); float dpi = ( p->device()->logicalDpiX() + p->device()->logicalDpiY() ) / 2; @@ -1250,7 +1250,7 @@ bool QgsVectorLayer::setSubsetString( QString subset ) bool QgsVectorLayer::simplifyDrawingCanbeApplied( int simplifyHint ) const { - return mDataProvider && ( mSimplifyDrawingHints & simplifyHint ) && !mEditBuffer && ( !mCurrentRendererContext || !mCurrentRendererContext->renderingPrintComposition() ); + return mDataProvider && ( mSimplifyDrawingHints & simplifyHint ) && !mEditBuffer && ( !mCurrentRendererContext || mCurrentRendererContext->useRenderingOptimization() ); } QgsFeatureIterator QgsVectorLayer::getFeatures( const QgsFeatureRequest& request ) From 4caed1c3a75a15908b1bc3de9420e42525fafa57 Mon Sep 17 00:00:00 2001 From: Alvaro Huarte Date: Wed, 18 Dec 2013 14:08:51 +0100 Subject: [PATCH 02/24] #8725-R: show map2pixel threshold in panels --- src/app/qgsoptions.cpp | 2 + src/app/qgsvectorlayerproperties.cpp | 2 + src/ui/qgsoptionsbase.ui | 312 +++++++++++++------------ src/ui/qgsvectorlayerpropertiesbase.ui | 16 +- 4 files changed, 178 insertions(+), 154 deletions(-) diff --git a/src/app/qgsoptions.cpp b/src/app/qgsoptions.cpp index f2c304b5f3ea..f1341ebfcac9 100644 --- a/src/app/qgsoptions.cpp +++ b/src/app/qgsoptions.cpp @@ -565,6 +565,7 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) : mSimplifyDrawingGroupBox->setChecked( settings.value( "/qgis/simplifyDrawingHints", ( int )QgsVectorLayer::DefaultSimplification ).toInt() != QgsVectorLayer::NoSimplification ); mSimplifyDrawingSlider->setValue(( int )( 5.0f * ( settings.value( "/qgis/simplifyDrawingTol", QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ).toFloat() - 1 ) ) ); mSimplifyDrawingPanel->setVisible( mSimplifyDrawingSlider->value() > 0 ); + mSimplifyDrawingPx->setText( QString( "(%1 px)" ).arg( 1.0f + 0.2f * mSimplifyDrawingSlider->value() ) ); // Slightly awkard here at the settings value is true to use QImage, // but the checkbox is true to use QPixmap @@ -2088,5 +2089,6 @@ void QgsOptions::saveDefaultDatumTransformations() void QgsOptions::on_mSimplifyDrawingSlider_valueChanged( int value ) { mSimplifyDrawingPanel->setVisible( value > 0 ); + mSimplifyDrawingPx->setText( QString( "(%1 px)" ).arg( 1.0f + 0.2f * value ) ); } diff --git a/src/app/qgsvectorlayerproperties.cpp b/src/app/qgsvectorlayerproperties.cpp index 4ff07602b436..86ae538db263 100644 --- a/src/app/qgsvectorlayerproperties.cpp +++ b/src/app/qgsvectorlayerproperties.cpp @@ -396,6 +396,7 @@ void QgsVectorLayerProperties::syncToLayer( void ) mSimplifyDrawingGroupBox->setChecked( layer->simplifyDrawingHints() != QgsVectorLayer::NoSimplification ); mSimplifyDrawingSlider->setValue(( int )( 5.0f * ( layer->simplifyDrawingTol() - 1 ) ) ); mSimplifyDrawingPanel->setVisible( mSimplifyDrawingSlider->value() > 0 ); + mSimplifyDrawingPx->setText( QString( "(%1 px)" ).arg( 1.0f + 0.2f * mSimplifyDrawingSlider->value() ) ); // load appropriate symbology page (V1 or V2) updateSymbologyPage(); @@ -1086,4 +1087,5 @@ void QgsVectorLayerProperties::on_mMaximumScaleSetCurrentPushButton_clicked() void QgsVectorLayerProperties::on_mSimplifyDrawingSlider_valueChanged( int value ) { mSimplifyDrawingPanel->setVisible( value > 0 ); + mSimplifyDrawingPx->setText( QString( "(%1 px)" ).arg( 1.0f + 0.2f * value ) ); } diff --git a/src/ui/qgsoptionsbase.ui b/src/ui/qgsoptionsbase.ui index 6d5b1750d161..fb04a431a6b3 100644 --- a/src/ui/qgsoptionsbase.ui +++ b/src/ui/qgsoptionsbase.ui @@ -1681,182 +1681,192 @@ - - - - Simplify geometries by default - - - true - - - - - - - 0 - 0 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + + Simplify geometries by default + + + true + + + + + + + 0 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If checked, new vector layers added to the map will automatically use geometry simplification to speed up rendering. The simplification applies only during rendering of the layer and does not modify the layer geometry.</p></body></html> - - - true - - - 2 - - - - - - - Simplification factor (higher values result in more simplification): - - - 2 - - - - - - - - 130 - 16777215 - - - - Higher values result in more simplification - - - 0 - - - 20 - - - 0 - - - true - - - Qt::Horizontal - - - false - - - false - - - - - - - - 0 - 70 - - - - - 16777215 - 16777215 - - - - QFrame::Box - - - QFrame::Raised - - - - - 10 - 0 - 60 - 67 - - - - 0 - 0 - + + true - - - 60 - 67 - + + 2 + + + + + + + Simplification threshold (higher values result in more simplification): + + 2 + + + + + - 40 - 40 + 130 + 16777215 - - Qt::LeftToRight + + Higher values result in more simplification - - false + + 0 - - + + 20 - - :/images/themes/default/mIconWarn.png + + 0 + + + true - + + Qt::Horizontal + + false - - - - - 45 - 8 - 411 - 51 - + + false + + + + - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + (0 px) + + + 2 + + + + + + + + 0 + 70 + + + + + 16777215 + 16777215 + + + + QFrame::Box + + + QFrame::Raised + + + + + 10 + 0 + 60 + 67 + + + + + 0 + 0 + + + + + 60 + 67 + + + + + 40 + 40 + + + + Qt::LeftToRight + + + false + + + + + + :/images/themes/default/mIconWarn.png + + + false + + + + + + 45 + 8 + 411 + 51 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><span style=" font-size:8pt; font-weight:600;">Warning:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> Increasing this factor will further speed up rendering, but may result in gaps </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> Increasing this threshold may speed up rendering, but may result in gaps </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> or topological errors in the layer display.</span></p></body></html> - + + - - - - - - Qt::Horizontal - - - - 20 - 20 - - - - - - - + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + diff --git a/src/ui/qgsvectorlayerpropertiesbase.ui b/src/ui/qgsvectorlayerpropertiesbase.ui index fab2c39be78b..1eb9069bc31c 100644 --- a/src/ui/qgsvectorlayerpropertiesbase.ui +++ b/src/ui/qgsvectorlayerpropertiesbase.ui @@ -976,7 +976,7 @@ p, li { white-space: pre-wrap; } - Simplification factor (higher values result in more simplification): + Simplification threshold (higher values result in more simplification): 2 @@ -1017,7 +1017,17 @@ p, li { white-space: pre-wrap; } - + + + + (0 px) + + + 2 + + + + @@ -1095,7 +1105,7 @@ p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><span style=" font-size:8pt; font-weight:600;">Warning:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> Increasing this factor will further speed up rendering, but may result in gaps </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> Increasing this threshold may speed up rendering, but may result in gaps </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> or topological errors in the layer display.</span></p></body></html> From 2a6f88c0a3c6423fc11a27be8a0674eee711060e Mon Sep 17 00:00:00 2001 From: Alvaro Huarte Date: Fri, 20 Dec 2013 10:54:09 +0100 Subject: [PATCH 03/24] #8725-R: simplifier execute in rendering loop --- src/core/qgsfeaturerequest.cpp | 33 --- src/core/qgsfeaturerequest.h | 23 +- src/core/qgsgeometrysimplifier.cpp | 4 +- src/core/qgsgeometrysimplifier.h | 8 +- src/core/qgsmaptopixelgeometrysimplifier.cpp | 4 +- src/core/qgsmaptopixelgeometrysimplifier.h | 4 +- src/core/qgsvectordataprovider.cpp | 6 - src/core/qgsvectordataprovider.h | 2 - src/core/qgsvectorlayer.cpp | 58 ++--- src/core/qgsvectorlayer.h | 5 +- src/core/qgsvectorlayerfeatureiterator.cpp | 44 ---- src/core/qgsvectorlayerfeatureiterator.h | 38 ---- src/providers/ogr/CMakeLists.txt | 2 +- src/providers/ogr/qgsogrfeatureiterator.cpp | 60 ------ src/providers/ogr/qgsogrfeatureiterator.h | 40 ---- .../qgsogrmaptopixelgeometrysimplifier.cpp | 201 ------------------ .../ogr/qgsogrmaptopixelgeometrysimplifier.h | 54 ----- src/providers/ogr/qgsogrprovider.cpp | 6 - 18 files changed, 47 insertions(+), 545 deletions(-) delete mode 100644 src/providers/ogr/qgsogrmaptopixelgeometrysimplifier.cpp delete mode 100644 src/providers/ogr/qgsogrmaptopixelgeometrysimplifier.h diff --git a/src/core/qgsfeaturerequest.cpp b/src/core/qgsfeaturerequest.cpp index dcea528997f0..6e33543310df 100644 --- a/src/core/qgsfeaturerequest.cpp +++ b/src/core/qgsfeaturerequest.cpp @@ -23,9 +23,6 @@ QgsFeatureRequest::QgsFeatureRequest() : mFilter( FilterNone ) , mFilterExpression( 0 ) , mFlags( 0 ) - , mMapCoordTransform( NULL ) - , mMapToPixel( NULL ) - , mMapToPixelTol( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ) { } @@ -34,9 +31,6 @@ QgsFeatureRequest::QgsFeatureRequest( QgsFeatureId fid ) , mFilterFid( fid ) , mFilterExpression( 0 ) , mFlags( 0 ) - , mMapCoordTransform( NULL ) - , mMapToPixel( NULL ) - , mMapToPixelTol( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ) { } @@ -45,9 +39,6 @@ QgsFeatureRequest::QgsFeatureRequest( const QgsRectangle& rect ) , mFilterRect( rect ) , mFilterExpression( 0 ) , mFlags( 0 ) - , mMapCoordTransform( NULL ) - , mMapToPixel( NULL ) - , mMapToPixelTol( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ) { } @@ -55,9 +46,6 @@ QgsFeatureRequest::QgsFeatureRequest( const QgsExpression& expr ) : mFilter( FilterExpression ) , mFilterExpression( new QgsExpression( expr.expression() ) ) , mFlags( 0 ) - , mMapCoordTransform( NULL ) - , mMapToPixel( NULL ) - , mMapToPixelTol( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ) { } @@ -82,9 +70,6 @@ QgsFeatureRequest& QgsFeatureRequest::operator=( const QgsFeatureRequest & rh ) mFilterExpression = 0; } mAttrs = rh.mAttrs; - mMapCoordTransform = rh.mMapCoordTransform; - mMapToPixel = rh.mMapToPixel; - mMapToPixelTol = rh.mMapToPixelTol; return *this; } @@ -189,21 +174,3 @@ bool QgsFeatureRequest::acceptFeature( const QgsFeature& feature ) return true; } - -QgsFeatureRequest& QgsFeatureRequest::setCoordinateTransform( const QgsCoordinateTransform* ct ) -{ - mMapCoordTransform = ct; - return *this; -} - -QgsFeatureRequest& QgsFeatureRequest::setMapToPixel( const QgsMapToPixel* mtp ) -{ - mMapToPixel = mtp; - return *this; -} - -QgsFeatureRequest& QgsFeatureRequest::setMapToPixelTol( float map2pixelTol ) -{ - mMapToPixelTol = map2pixelTol; - return *this; -} diff --git a/src/core/qgsfeaturerequest.h b/src/core/qgsfeaturerequest.h index 0960fd71e913..203f63d81f6e 100644 --- a/src/core/qgsfeaturerequest.h +++ b/src/core/qgsfeaturerequest.h @@ -21,9 +21,6 @@ #include "qgsrectangle.h" #include "qgsexpression.h" -#include "qgscoordinatetransform.h" -#include "qgsmaptopixel.h" - #include typedef QList QgsAttributeList; @@ -64,9 +61,7 @@ class CORE_EXPORT QgsFeatureRequest NoFlags = 0, NoGeometry = 1, //!< Geometry is not required. It may still be returned if e.g. required for a filter condition. SubsetOfAttributes = 2, //!< Fetch only a subset of attributes (setSubsetOfAttributes sets this flag) - ExactIntersect = 4, //!< Use exact geometry intersection (slower) instead of bounding boxes - SimplifyGeometry = 8, //!< The geometries can be simplified using the current map2pixel context state (e.g. for fast rendering...) - SimplifyEnvelope = 16 //!< The geometries can be fully simplified by its BoundingBox (e.g. for fast rendering...) + ExactIntersect = 4 //!< Use exact geometry intersection (slower) instead of bounding boxes }; Q_DECLARE_FLAGS( Flags, Flag ) @@ -140,15 +135,6 @@ class CORE_EXPORT QgsFeatureRequest // void setFilterNativeExpression(con QString& expr); // using provider's SQL (if supported) // void setLimit(int limit); - const QgsCoordinateTransform* coordinateTransform() const { return mMapCoordTransform; } - QgsFeatureRequest& setCoordinateTransform( const QgsCoordinateTransform* ct ); - - const QgsMapToPixel* mapToPixel() const { return mMapToPixel; } - QgsFeatureRequest& setMapToPixel( const QgsMapToPixel* mtp ); - - float mapToPixelTol() const { return mMapToPixelTol; } - QgsFeatureRequest& setMapToPixelTol( float map2pixelTol ); - protected: FilterType mFilter; QgsRectangle mFilterRect; @@ -157,13 +143,6 @@ class CORE_EXPORT QgsFeatureRequest QgsExpression* mFilterExpression; Flags mFlags; QgsAttributeList mAttrs; - - //! For transformation between coordinate systems from current layer to map target. Can be 0 if on-the-fly reprojection is not used - const QgsCoordinateTransform* mMapCoordTransform; - //! For transformation between map coordinates and device coordinates - const QgsMapToPixel* mMapToPixel; - //! Factor tolterance to apply in transformation between map coordinates and device coordinates - float mMapToPixelTol; }; Q_DECLARE_OPERATORS_FOR_FLAGS( QgsFeatureRequest::Flags ) diff --git a/src/core/qgsgeometrysimplifier.cpp b/src/core/qgsgeometrysimplifier.cpp index a45cdfac0b0f..5572addfbfa6 100644 --- a/src/core/qgsgeometrysimplifier.cpp +++ b/src/core/qgsgeometrysimplifier.cpp @@ -60,13 +60,13 @@ QgsTopologyPreservingSimplifier::~QgsTopologyPreservingSimplifier() } //! Returns a simplified version the specified geometry -QgsGeometry* QgsTopologyPreservingSimplifier::simplify( QgsGeometry* geometry ) +QgsGeometry* QgsTopologyPreservingSimplifier::simplify( QgsGeometry* geometry ) const { return geometry->simplify( mTolerance ); } //! Simplifies the specified geometry -bool QgsTopologyPreservingSimplifier::simplifyGeometry( QgsGeometry* geometry ) +bool QgsTopologyPreservingSimplifier::simplifyGeometry( QgsGeometry* geometry ) const { QgsGeometry* g = geometry->simplify( mTolerance ); diff --git a/src/core/qgsgeometrysimplifier.h b/src/core/qgsgeometrysimplifier.h index 9713cf2cb198..e6502e450f09 100644 --- a/src/core/qgsgeometrysimplifier.h +++ b/src/core/qgsgeometrysimplifier.h @@ -28,9 +28,9 @@ class CORE_EXPORT QgsAbstractGeometrySimplifier virtual ~QgsAbstractGeometrySimplifier(); //! Returns a simplified version the specified geometry - virtual QgsGeometry* simplify( QgsGeometry* geometry ) = 0; + virtual QgsGeometry* simplify( QgsGeometry* geometry ) const = 0; //! Simplifies the specified geometry - virtual bool simplifyGeometry( QgsGeometry* geometry ) = 0; + virtual bool simplifyGeometry( QgsGeometry* geometry ) const = 0; // MapToPixel simplification helper methods public: @@ -59,9 +59,9 @@ class CORE_EXPORT QgsTopologyPreservingSimplifier : public QgsAbstractGeometrySi public: //! Returns a simplified version the specified geometry - virtual QgsGeometry* simplify( QgsGeometry* geometry ); + virtual QgsGeometry* simplify( QgsGeometry* geometry ) const; //! Simplifies the specified geometry - virtual bool simplifyGeometry( QgsGeometry* geometry ); + virtual bool simplifyGeometry( QgsGeometry* geometry ) const; }; #endif // QGSGEOMETRYSIMPLIFIER_H diff --git a/src/core/qgsmaptopixelgeometrysimplifier.cpp b/src/core/qgsmaptopixelgeometrysimplifier.cpp index 446d5675d36e..962ebd86ac0d 100644 --- a/src/core/qgsmaptopixelgeometrysimplifier.cpp +++ b/src/core/qgsmaptopixelgeometrysimplifier.cpp @@ -352,7 +352,7 @@ bool QgsMapToPixelSimplifier::canbeGeneralizedByMapBoundingBox( const QgsRectang } //! Returns a simplified version the specified geometry (Removing duplicated points) when is applied the specified map2pixel context -QgsGeometry* QgsMapToPixelSimplifier::simplify( QgsGeometry* geometry ) +QgsGeometry* QgsMapToPixelSimplifier::simplify( QgsGeometry* geometry ) const { QgsGeometry* g = new QgsGeometry(); @@ -393,7 +393,7 @@ bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry* geometry, int simpl } //! Simplifies the geometry (Removing duplicated points) when is applied the specified map2pixel context -bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry* geometry ) +bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry* geometry ) const { return simplifyGeometry( geometry, mSimplifyFlags, mMapCoordTransform, mMapToPixel, mMapToPixelTol ); } diff --git a/src/core/qgsmaptopixelgeometrysimplifier.h b/src/core/qgsmaptopixelgeometrysimplifier.h index 2a3739ad1927..19e4735ad58b 100644 --- a/src/core/qgsmaptopixelgeometrysimplifier.h +++ b/src/core/qgsmaptopixelgeometrysimplifier.h @@ -77,9 +77,9 @@ class CORE_EXPORT QgsMapToPixelSimplifier : public QgsAbstractGeometrySimplifier void setMapToPixelTol( float map2pixelTol ) { mMapToPixelTol = map2pixelTol; } //! Returns a simplified version the specified geometry - virtual QgsGeometry* simplify( QgsGeometry* geometry ); + virtual QgsGeometry* simplify( QgsGeometry* geometry ) const; //! Simplifies the specified geometry - virtual bool simplifyGeometry( QgsGeometry* geometry ); + virtual bool simplifyGeometry( QgsGeometry* geometry ) const; // MapToPixel simplification helper methods public: diff --git a/src/core/qgsvectordataprovider.cpp b/src/core/qgsvectordataprovider.cpp index 614daa30fe8e..3ec4cba39e9d 100644 --- a/src/core/qgsvectordataprovider.cpp +++ b/src/core/qgsvectordataprovider.cpp @@ -194,12 +194,6 @@ QString QgsVectorDataProvider::capabilitiesString() const QgsDebugMsg( "Capability: Change Geometries" ); } - if ( abilities & QgsVectorDataProvider::SimplifyGeometries ) - { - abilitiesList += tr( "Simplify Geometries" ); - QgsDebugMsg( "Capability: Simplify Geometries before fetch the feature" ); - } - return abilitiesList.join( ", " ); } diff --git a/src/core/qgsvectordataprovider.h b/src/core/qgsvectordataprovider.h index 5758eb600d77..00ec22287ca4 100644 --- a/src/core/qgsvectordataprovider.h +++ b/src/core/qgsvectordataprovider.h @@ -86,8 +86,6 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider CreateAttributeIndex = 1 << 12, /** allows user to select encoding */ SelectEncoding = 1 << 13, - /** supports simplification of geometries before fetch the feature */ - SimplifyGeometries = 1 << 14, }; /** bitmask of all provider's editing capabilities */ diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index e8854f24a495..2a2812259616 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -400,7 +400,7 @@ void QgsVectorLayer::drawLabels( QgsRenderContext& rendererContext ) -void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling ) +void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling, const QgsAbstractGeometrySimplifier* geometrySimplifier ) { if ( !hasGeometryType() ) return; @@ -451,6 +451,13 @@ void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& bool sel = mSelectedFeatureIds.contains( fet.id() ); bool drawMarker = ( mEditBuffer && ( !vertexMarkerOnlyForSelection || sel ) ); + // simplify the geometry using the current map2pixel context + if ( geometrySimplifier ) + { + fet = QgsFeature( fet ); + geometrySimplifier->simplifyGeometry( fet.geometry() ); + } + // render feature bool rendered = mRendererV2->renderFeature( fet, rendererContext, -1, sel, drawMarker ); @@ -493,7 +500,7 @@ void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& #endif } -void QgsVectorLayer::drawRendererV2Levels( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling ) +void QgsVectorLayer::drawRendererV2Levels( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling, const QgsAbstractGeometrySimplifier* geometrySimplifier ) { if ( !hasGeometryType() ) return; @@ -539,6 +546,13 @@ void QgsVectorLayer::drawRendererV2Levels( QgsFeatureIterator &fit, QgsRenderCon continue; } + // simplify the geometry using the current map2pixel context + if ( geometrySimplifier ) + { + fet = QgsFeature( fet ); + geometrySimplifier->simplifyGeometry( fet.geometry() ); + } + if ( !features.contains( sym ) ) { features.insert( sym, QList() ); @@ -698,14 +712,14 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext ) //do startRender before getFeatures to give renderers the possibility of querying features in the startRender method mRendererV2->startRender( rendererContext, this ); - QgsFeatureRequest& featureRequest = QgsFeatureRequest() - .setFilterRect( rendererContext.extent() ) - .setSubsetOfAttributes( attributes ); + QgsFeatureIterator fit = getFeatures( QgsFeatureRequest() + .setFilterRect( rendererContext.extent() ) + .setSubsetOfAttributes( attributes ) ); - QgsFeatureIterator fit = QgsFeatureIterator(); + QgsAbstractGeometrySimplifier* geometrySimplifier = NULL; - // Enable the simplification of the geometries (Using the current map2pixel context) before fetch the features. - if ( simplifyDrawingCanbeApplied( QgsVectorLayer::GeometrySimplification | QgsVectorLayer::EnvelopeSimplification ) && !( featureRequest.flags() & QgsFeatureRequest::NoGeometry ) ) + // enable the simplification of the geometries (Using the current map2pixel context) before send it to renderer engine. + if ( simplifyDrawingCanbeApplied( QgsVectorLayer::GeometrySimplification | QgsVectorLayer::EnvelopeSimplification ) ) { QPainter* p = rendererContext.painter(); float dpi = ( p->device()->logicalDpiX() + p->device()->logicalDpiY() ) / 2; @@ -715,29 +729,21 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext ) if ( mSimplifyDrawingHints & QgsVectorLayer::GeometrySimplification ) simplifyFlags |= QgsMapToPixelSimplifier::SimplifyGeometry; if ( mSimplifyDrawingHints & QgsVectorLayer::EnvelopeSimplification ) simplifyFlags |= QgsMapToPixelSimplifier::SimplifyEnvelope; - QgsFeatureRequest::Flags requestFlags = QgsFeatureRequest::NoFlags; - if ( mSimplifyDrawingHints & QgsVectorLayer::GeometrySimplification ) requestFlags |= QgsFeatureRequest::SimplifyGeometry; - if ( mSimplifyDrawingHints & QgsVectorLayer::EnvelopeSimplification ) requestFlags |= QgsFeatureRequest::SimplifyEnvelope; - - featureRequest.setFlags( featureRequest.flags() | requestFlags ); - featureRequest.setCoordinateTransform( rendererContext.coordinateTransform() ); - featureRequest.setMapToPixel( &rendererContext.mapToPixel() ); - featureRequest.setMapToPixelTol( map2pixelTol ); - - QgsMapToPixelSimplifier* simplifier = + geometrySimplifier = new QgsMapToPixelSimplifier( simplifyFlags, rendererContext.coordinateTransform(), &rendererContext.mapToPixel(), map2pixelTol ); - - fit = QgsFeatureIterator( new QgsSimplifiedVectorLayerFeatureIterator( this, featureRequest, simplifier ) ); - } - else - { - fit = getFeatures( featureRequest ); } if (( mRendererV2->capabilities() & QgsFeatureRendererV2::SymbolLevels ) && mRendererV2->usingSymbolLevels() ) - drawRendererV2Levels( fit, rendererContext, labeling ); + drawRendererV2Levels( fit, rendererContext, labeling, geometrySimplifier ); else - drawRendererV2( fit, rendererContext, labeling ); + drawRendererV2( fit, rendererContext, labeling, geometrySimplifier ); + + // release the optional geometry simplifier + if ( geometrySimplifier ) + { + delete geometrySimplifier; + geometrySimplifier = NULL; + } return true; } diff --git a/src/core/qgsvectorlayer.h b/src/core/qgsvectorlayer.h index ceb2675a4046..de39c01d239b 100644 --- a/src/core/qgsvectorlayer.h +++ b/src/core/qgsvectorlayer.h @@ -57,6 +57,7 @@ class QgsDiagramLayerSettings; class QgsGeometryCache; class QgsVectorLayerEditBuffer; class QgsSymbolV2; +class QgsAbstractGeometrySimplifier; typedef QList QgsAttributeList; typedef QSet QgsAttributeIds; @@ -729,12 +730,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer /** Draw layer with renderer V2. QgsFeatureRenderer::startRender() needs to be called before using this method * @note added in 1.4 */ - void drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling ); + void drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling, const QgsAbstractGeometrySimplifier* geometrySimplifier = NULL ); /** Draw layer with renderer V2 using symbol levels. QgsFeatureRenderer::startRender() needs to be called before using this method * @note added in 1.4 */ - void drawRendererV2Levels( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling ); + void drawRendererV2Levels( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling, const QgsAbstractGeometrySimplifier* geometrySimplifier = NULL ); /** Returns point, line or polygon */ QGis::GeometryType geometryType() const; diff --git a/src/core/qgsvectorlayerfeatureiterator.cpp b/src/core/qgsvectorlayerfeatureiterator.cpp index 7fa4856b1b0c..731cdd137583 100644 --- a/src/core/qgsvectorlayerfeatureiterator.cpp +++ b/src/core/qgsvectorlayerfeatureiterator.cpp @@ -589,47 +589,3 @@ void QgsVectorLayerFeatureIterator::updateFeatureGeometry( QgsFeature &f ) if ( mChangedGeometries.contains( f.id() ) ) f.setGeometry( mChangedGeometries[f.id()] ); } - -/*************************************************************************** - QgsSimplifiedVectorLayerFeatureIterator class - ---------------------- - begin : December 2013 - copyright : (C) 2013 by Alvaro Huarte - email : http://wiki.osgeo.org/wiki/Alvaro_Huarte - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -QgsSimplifiedVectorLayerFeatureIterator::QgsSimplifiedVectorLayerFeatureIterator( QgsVectorLayer* layer, const QgsFeatureRequest& request, QgsAbstractGeometrySimplifier* simplifier ) - : QgsVectorLayerFeatureIterator( layer, request ) - , mSimplifier( simplifier ) -{ - mSupportsPresimplify = layer->dataProvider()->capabilities() & QgsVectorDataProvider::SimplifyGeometries; -} - -QgsSimplifiedVectorLayerFeatureIterator::~QgsSimplifiedVectorLayerFeatureIterator() -{ - if ( mSimplifier ) - { - delete mSimplifier; - mSimplifier = NULL; - } -} - -//! fetch next feature, return true on success -bool QgsSimplifiedVectorLayerFeatureIterator::fetchFeature( QgsFeature& feature ) -{ - if ( QgsVectorLayerFeatureIterator::fetchFeature( feature ) ) - { - const QgsMapToPixel* mtp = mRequest.mapToPixel(); - if ( mtp && !mSupportsPresimplify && mSimplifier ) mSimplifier->simplifyGeometry( feature.geometry() ); - return true; - } - return false; -} diff --git a/src/core/qgsvectorlayerfeatureiterator.h b/src/core/qgsvectorlayerfeatureiterator.h index e2fe4363ede0..077dc6f31659 100644 --- a/src/core/qgsvectorlayerfeatureiterator.h +++ b/src/core/qgsvectorlayerfeatureiterator.h @@ -116,42 +116,4 @@ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureItera QMap mFetchJoinInfo; }; -/*************************************************************************** - QgsSimplifiedVectorLayerFeatureIterator class - ---------------------- - begin : December 2013 - copyright : (C) 2013 by Alvaro Huarte - email : http://wiki.osgeo.org/wiki/Alvaro_Huarte - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#include "qgsgeometrysimplifier.h" - -//! Provides a specialized VectorLayerFeatureIterator for enable simplification of the geometries fetched -class CORE_EXPORT QgsSimplifiedVectorLayerFeatureIterator : public QgsVectorLayerFeatureIterator -{ - public: - QgsSimplifiedVectorLayerFeatureIterator( QgsVectorLayer* layer, const QgsFeatureRequest& request, QgsAbstractGeometrySimplifier* simplifier ); - ~QgsSimplifiedVectorLayerFeatureIterator( ); - - protected: - //! fetch next feature, return true on success - virtual bool fetchFeature( QgsFeature& feature ); - - private: - //! Related geometry simplifier - QgsAbstractGeometrySimplifier* mSimplifier; - //! Indicates the related vector provider supports simplify the geometries before fecth the feature - bool mSupportsPresimplify; -}; - -/***************************************************************************/ - #endif // QGSVECTORLAYERFEATUREITERATOR_H diff --git a/src/providers/ogr/CMakeLists.txt b/src/providers/ogr/CMakeLists.txt index 644c27b703e3..710c1c3995b8 100644 --- a/src/providers/ogr/CMakeLists.txt +++ b/src/providers/ogr/CMakeLists.txt @@ -1,5 +1,5 @@ -SET (OGR_SRCS qgsogrprovider.cpp qgsogrdataitems.cpp qgsogrfeatureiterator.cpp qgsogrmaptopixelgeometrysimplifier.cpp) +SET (OGR_SRCS qgsogrprovider.cpp qgsogrdataitems.cpp qgsogrfeatureiterator.cpp) SET(OGR_MOC_HDRS qgsogrprovider.h qgsogrdataitems.h) diff --git a/src/providers/ogr/qgsogrfeatureiterator.cpp b/src/providers/ogr/qgsogrfeatureiterator.cpp index 8e034e5c5cee..86496bd59a23 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.cpp +++ b/src/providers/ogr/qgsogrfeatureiterator.cpp @@ -233,8 +233,6 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature ) if ( geom ) { - fetchedFeature( fet, geom ); - // get the wkb representation int memorySize = OGR_G_WkbSize( geom ); unsigned char *wkb = new unsigned char[memorySize]; @@ -276,61 +274,3 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature ) return true; } - -//! Notified a new OGRFeatureH fecthed from data provider -void QgsOgrFeatureIterator::fetchedFeature( OGRFeatureH feature, OGRGeometryH geometry ) -{ - Q_UNUSED( feature ); - Q_UNUSED( geometry ); -} - -/*************************************************************************** - QgsOgrSimplifiedFeatureIterator class - ---------------------- - begin : December 2013 - copyright : (C) 2013 by Alvaro Huarte - email : http://wiki.osgeo.org/wiki/Alvaro_Huarte - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -//! Provides a specialized FeatureIterator for enable simplification of the geometries -QgsOgrSimplifiedFeatureIterator::QgsOgrSimplifiedFeatureIterator( QgsOgrProvider* p, const QgsFeatureRequest& request ) - : QgsOgrFeatureIterator( p, request ) - , mSimplifier( NULL ) -{ - QgsFeatureRequest::Flags requestFlags = request.flags(); - - int simplifyFlags = QgsMapToPixelSimplifier::NoFlags; - if ( requestFlags & QgsFeatureRequest::SimplifyGeometry ) simplifyFlags |= QgsMapToPixelSimplifier::SimplifyGeometry; - if ( requestFlags & QgsFeatureRequest::SimplifyEnvelope ) simplifyFlags |= QgsMapToPixelSimplifier::SimplifyEnvelope; - - if ( simplifyFlags != QgsMapToPixelSimplifier::NoFlags ) - { - mSimplifier = new QgsOgrMapToPixelSimplifier( simplifyFlags, request.coordinateTransform(), request.mapToPixel(), request.mapToPixelTol() ); - } -} -QgsOgrSimplifiedFeatureIterator::~QgsOgrSimplifiedFeatureIterator( ) -{ - if ( mSimplifier ) - { - delete mSimplifier; - mSimplifier = NULL; - } -} - -//! Notified a new OGRFeatureH fecthed from data provider -void QgsOgrSimplifiedFeatureIterator::fetchedFeature( OGRFeatureH feature, OGRGeometryH geometry ) -{ - if ( mSimplifier && ( mSimplifier->simplifyFlags() & ( QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope ) ) ) - { - mSimplifier->simplifyGeometry(( OGRGeometry* ) geometry ); - } - QgsOgrFeatureIterator::fetchedFeature( feature, geometry ); -} diff --git a/src/providers/ogr/qgsogrfeatureiterator.h b/src/providers/ogr/qgsogrfeatureiterator.h index 0e62ab3c796e..0c1957fafbcf 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.h +++ b/src/providers/ogr/qgsogrfeatureiterator.h @@ -47,9 +47,6 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator //! Get an attribute associated with a feature void getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex ); - //! Notified a new OGRFeatureH fecthed from data provider - virtual void fetchedFeature( OGRFeatureH feature, OGRGeometryH geometry ); - bool mFeatureFetched; OGRDataSourceH ogrDataSource; @@ -61,41 +58,4 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator bool mFetchGeometry; }; -/*************************************************************************** - QgsOgrSimplifiedFeatureIterator class - ---------------------- - begin : December 2013 - copyright : (C) 2013 by Alvaro Huarte - email : http://wiki.osgeo.org/wiki/Alvaro_Huarte - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#include "qgsogrmaptopixelgeometrysimplifier.h" - -class OGRRawPoint; -class OGRGeometry; - -//! Provides a specialized FeatureIterator for enable simplification of the geometries fetched -class QgsOgrSimplifiedFeatureIterator : public QgsOgrFeatureIterator -{ - public: - QgsOgrSimplifiedFeatureIterator( QgsOgrProvider* p, const QgsFeatureRequest& request ); - ~QgsOgrSimplifiedFeatureIterator( ); - - protected: - //! Notified a new OGRFeatureH fecthed from data provider - virtual void fetchedFeature( OGRFeatureH feature, OGRGeometryH geometry ); - - private: - //! Related geometry simplifier - QgsOgrMapToPixelSimplifier* mSimplifier; -}; - #endif // QGSOGRFEATUREITERATOR_H diff --git a/src/providers/ogr/qgsogrmaptopixelgeometrysimplifier.cpp b/src/providers/ogr/qgsogrmaptopixelgeometrysimplifier.cpp deleted file mode 100644 index 172eba1096c8..000000000000 --- a/src/providers/ogr/qgsogrmaptopixelgeometrysimplifier.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/*************************************************************************** - qgsogrmaptopixelgeometrysimplifier.cpp - --------------------- - begin : December 2013 - copyright : (C) 2013 by Alvaro Huarte - email : http://wiki.osgeo.org/wiki/Alvaro_Huarte - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#include "qgsogrmaptopixelgeometrysimplifier.h" -#include "qgsogrprovider.h" - -QgsOgrMapToPixelSimplifier::QgsOgrMapToPixelSimplifier( int simplifyFlags, const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapTolPixel, float mapToPixelTol ) : QgsMapToPixelSimplifier( simplifyFlags, coordinateTransform, mapTolPixel, mapToPixelTol ) -{ - mPointBufferCount = 512; - mPointBufferPtr = ( OGRRawPoint* )OGRMalloc( mPointBufferCount * sizeof( OGRRawPoint ) ); -} -QgsOgrMapToPixelSimplifier::~QgsOgrMapToPixelSimplifier() -{ - if ( mPointBufferPtr ) - { - OGRFree( mPointBufferPtr ); - mPointBufferPtr = NULL; - } -} - -//! Returns a point buffer of the specified size -OGRRawPoint* QgsOgrMapToPixelSimplifier::mallocPoints( int numPoints ) -{ - if ( mPointBufferPtr && mPointBufferCount < numPoints ) - { - OGRFree( mPointBufferPtr ); - mPointBufferPtr = NULL; - } - if ( mPointBufferPtr == NULL ) - { - mPointBufferCount = numPoints; - mPointBufferPtr = ( OGRRawPoint* )OGRMalloc( mPointBufferCount * sizeof( OGRRawPoint ) ); - } - return mPointBufferPtr; -} - -////////////////////////////////////////////////////////////////////////////////////////////// -// Helper simplification methods - -//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context -bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( QGis::GeometryType geometryType, const QgsRectangle& envelope, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount ) -{ - bool canbeGeneralizable = ( mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyGeometry ); - - pointSimplifiedCount = pointCount; - if ( geometryType == QGis::Point || geometryType == QGis::UnknownGeometry ) return false; - pointSimplifiedCount = 0; - - double map2pixelTol = mMapToPixelTol * QgsMapToPixelSimplifier::calculateViewPixelTolerance( envelope, mMapCoordTransform, mMapToPixel ); - map2pixelTol *= map2pixelTol; //-> Use mappixelTol for 'LengthSquare' calculations. - double x, y, lastX = 0, lastY = 0; - - char* xsourcePtr = ( char* )xptr; - char* ysourcePtr = ( char* )yptr; - char* xtargetPtr = ( char* )xptr; - char* ytargetPtr = ( char* )yptr; - - for ( int i = 0, numPoints = geometryType == QGis::Polygon ? pointCount - 1 : pointCount; i < numPoints; ++i ) - { - memcpy( &x, xsourcePtr, sizeof( double ) ); xsourcePtr += xStride; - memcpy( &y, ysourcePtr, sizeof( double ) ); ysourcePtr += yStride; - - if ( i == 0 || !canbeGeneralizable || QgsMapToPixelSimplifier::calculateLengthSquared2D( x, y, lastX, lastY ) > map2pixelTol ) - { - memcpy( xtargetPtr, &x, sizeof( double ) ); lastX = x; xtargetPtr += xStride; - memcpy( ytargetPtr, &y, sizeof( double ) ); lastY = y; ytargetPtr += yStride; - pointSimplifiedCount++; - } - } - if ( geometryType == QGis::Polygon ) - { - memcpy( xtargetPtr, xptr, sizeof( double ) ); - memcpy( ytargetPtr, yptr, sizeof( double ) ); - pointSimplifiedCount++; - } - return pointSimplifiedCount != pointCount; -} - -//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context -bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometry* geometry, bool isaLinearRing ) -{ - OGRwkbGeometryType wkbGeometryType = wkbFlatten( geometry->getGeometryType() ); - - // Simplify the geometry rewriting temporally its WKB-stream for saving calloc's. - if ( wkbGeometryType == wkbLineString ) - { - OGRLineString* lineString = ( OGRLineString* )geometry; - - int numPoints = lineString->getNumPoints(); - if (( isaLinearRing && numPoints <= 5 ) || ( !isaLinearRing && numPoints <= 2 ) ) return false; - - OGREnvelope env; - geometry->getEnvelope( &env ); - QgsRectangle envelope( env.MinX, env.MinY, env.MaxX, env.MaxY ); - - // Can replace the geometry by its BBOX ? - if (( mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyEnvelope ) && canbeGeneralizedByMapBoundingBox( envelope ) ) - { - OGRRawPoint* points = NULL; - int numPoints = 0; - - double x1 = envelope.xMinimum(); - double y1 = envelope.yMinimum(); - double x2 = envelope.xMaximum(); - double y2 = envelope.yMaximum(); - - if ( isaLinearRing ) - { - numPoints = 5; - points = mallocPoints( numPoints ); - points[0].x = x1; points[0].y = y1; - points[1].x = x2; points[1].y = y1; - points[2].x = x2; points[2].y = y2; - points[3].x = x1; points[3].y = y2; - points[4].x = x1; points[4].y = y1; - } - else - { - numPoints = 2; - points = mallocPoints( numPoints ); - points[0].x = x1; points[0].y = y1; - points[1].x = x2; points[1].y = y2; - } - lineString->setPoints( numPoints, points ); - lineString->flattenTo2D(); - return true; - } - else - if ( mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyGeometry ) - { - QGis::GeometryType geometryType = isaLinearRing ? QGis::Polygon : QGis::Line; - int numSimplifiedPoints = 0; - - OGRRawPoint* points = mallocPoints( numPoints ); - double* xptr = ( double* )points; - double* yptr = xptr + 1; - lineString->getPoints( points ); - - if ( simplifyOgrGeometry( geometryType, envelope, xptr, 16, yptr, 16, numPoints, numSimplifiedPoints ) ) - { - lineString->setPoints( numSimplifiedPoints, points ); - lineString->flattenTo2D(); - } - return numSimplifiedPoints != numPoints; - } - } - else - if ( wkbGeometryType == wkbPolygon ) - { - OGRPolygon* polygon = ( OGRPolygon* )geometry; - bool result = simplifyOgrGeometry( polygon->getExteriorRing(), true ); - - for ( int i = 0, numInteriorRings = polygon->getNumInteriorRings(); i < numInteriorRings; ++i ) - { - result |= simplifyOgrGeometry( polygon->getInteriorRing( i ), true ); - } - if ( result ) polygon->flattenTo2D(); - return result; - } - else - if ( wkbGeometryType == wkbMultiLineString || wkbGeometryType == wkbMultiPolygon ) - { - OGRGeometryCollection* collection = ( OGRGeometryCollection* )geometry; - bool result = false; - - for ( int i = 0, numGeometries = collection->getNumGeometries(); i < numGeometries; ++i ) - { - result |= simplifyOgrGeometry( collection->getGeometryRef( i ), wkbGeometryType == wkbMultiPolygon ); - } - if ( result ) collection->flattenTo2D(); - return result; - } - return false; -} - -////////////////////////////////////////////////////////////////////////////////////////////// - -//! Simplifies the specified geometry -bool QgsOgrMapToPixelSimplifier::simplifyGeometry( OGRGeometry* geometry ) -{ - OGRwkbGeometryType wkbGeometryType = QgsOgrProvider::ogrWkbSingleFlatten( geometry->getGeometryType() ); - - if ( wkbGeometryType == wkbLineString || wkbGeometryType == wkbPolygon ) - { - return simplifyOgrGeometry( geometry, wkbGeometryType == wkbPolygon ); - } - return false; -} diff --git a/src/providers/ogr/qgsogrmaptopixelgeometrysimplifier.h b/src/providers/ogr/qgsogrmaptopixelgeometrysimplifier.h deleted file mode 100644 index 736043caef99..000000000000 --- a/src/providers/ogr/qgsogrmaptopixelgeometrysimplifier.h +++ /dev/null @@ -1,54 +0,0 @@ -/*************************************************************************** - qgsogrmaptopixelgeometrysimplifier.h - --------------------- - begin : December 2013 - copyright : (C) 2013 by Alvaro Huarte - email : http://wiki.osgeo.org/wiki/Alvaro_Huarte - - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#ifndef QGSOGRMAPTOPIXELGEOMETRYSIMPLIFIER_H -#define QGSOGRMAPTOPIXELGEOMETRYSIMPLIFIER_H - -#include "qgsmaptopixelgeometrysimplifier.h" -#include - -/** - * OGR implementation of GeometrySimplifier using the "MapToPixel" algorithm - * - * Simplifies a geometry removing points within of the maximum distance difference that defines the MapToPixel info of a RenderContext request. - * This class enables simplify the geometries to be rendered in a MapCanvas target to speed up the vector drawing. - */ -class QgsOgrMapToPixelSimplifier : public QgsMapToPixelSimplifier -{ - public: - QgsOgrMapToPixelSimplifier( int simplifyFlags, const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapToPixel, float mapToPixelTol ); - virtual ~QgsOgrMapToPixelSimplifier(); - - private: - //! Point memory buffer for optimize the simplification process - OGRRawPoint* mPointBufferPtr; - //! Current Point memory buffer size - int mPointBufferCount; - - //! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context - bool simplifyOgrGeometry( QGis::GeometryType geometryType, const QgsRectangle& envelope, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount ); - //! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context - bool simplifyOgrGeometry( OGRGeometry* geometry, bool isaLinearRing ); - - //! Returns a point buffer of the specified size - OGRRawPoint* mallocPoints( int numPoints ); - - public: - //! Simplifies the specified geometry - bool simplifyGeometry( OGRGeometry* geometry ); -}; - -#endif // QGSOGRMAPTOPIXELGEOMETRYSIMPLIFIER_H diff --git a/src/providers/ogr/qgsogrprovider.cpp b/src/providers/ogr/qgsogrprovider.cpp index 80bb669b7789..2b5faec0ebe9 100644 --- a/src/providers/ogr/qgsogrprovider.cpp +++ b/src/providers/ogr/qgsogrprovider.cpp @@ -808,9 +808,6 @@ void QgsOgrProvider::setRelevantFields( OGRLayerH ogrLayer, bool fetchGeometry, QgsFeatureIterator QgsOgrProvider::getFeatures( const QgsFeatureRequest& request ) { - if ( request.flags() & ( QgsFeatureRequest::SimplifyGeometry | QgsFeatureRequest::SimplifyEnvelope ) ) - return QgsFeatureIterator( new QgsOgrSimplifiedFeatureIterator( this, request ) ); - return QgsFeatureIterator( new QgsOgrFeatureIterator( this, request ) ); } @@ -1496,9 +1493,6 @@ int QgsOgrProvider::capabilities() const ability &= ~( AddAttributes | DeleteFeatures ); } } - - // By default, supports simplification of geometries before fetch the OGR-feature. - ability |= SimplifyGeometries; } return ability; From ffa2e3312b2a38ae37ea60e6ab1e1ac945bf9203 Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Tue, 24 Dec 2013 07:51:26 +0100 Subject: [PATCH 04/24] #8725-R: define QgsSimplifyMethod Define QgsSimplifyMethod to use as optional parameter in QgsFeatureRequest --- src/core/CMakeLists.txt | 1 + src/core/qgsfeaturerequest.cpp | 8 ++++- src/core/qgsfeaturerequest.h | 7 ++++ src/core/qgssimplifymethod.cpp | 52 ++++++++++++++++++++++++++++ src/core/qgssimplifymethod.h | 63 ++++++++++++++++++++++++++++++++++ 5 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 src/core/qgssimplifymethod.cpp create mode 100644 src/core/qgssimplifymethod.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5b9dc5fc8ddb..9f78a8fb6aa4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -75,6 +75,7 @@ SET(QGIS_CORE_SRCS qgsgeometrycache.cpp qgsgeometryvalidator.cpp qgsgeometrysimplifier.cpp + qgssimplifymethod.cpp qgsgml.cpp qgsgmlschema.cpp qgshttptransaction.cpp diff --git a/src/core/qgsfeaturerequest.cpp b/src/core/qgsfeaturerequest.cpp index 6e33543310df..1b407cf867a2 100644 --- a/src/core/qgsfeaturerequest.cpp +++ b/src/core/qgsfeaturerequest.cpp @@ -70,6 +70,7 @@ QgsFeatureRequest& QgsFeatureRequest::operator=( const QgsFeatureRequest & rh ) mFilterExpression = 0; } mAttrs = rh.mAttrs; + mSimplifyMethod = rh.mSimplifyMethod; return *this; } @@ -120,7 +121,6 @@ QgsFeatureRequest& QgsFeatureRequest::setSubsetOfAttributes( const QgsAttributeL return *this; } - QgsFeatureRequest& QgsFeatureRequest::setSubsetOfAttributes( const QStringList& attrNames, const QgsFields& fields ) { mFlags |= SubsetOfAttributes; @@ -135,6 +135,12 @@ QgsFeatureRequest& QgsFeatureRequest::setSubsetOfAttributes( const QStringList& return *this; } +QgsFeatureRequest& QgsFeatureRequest::setSimplifyMethod( const QgsSimplifyMethod& simplifyMethod ) +{ + mSimplifyMethod = simplifyMethod; + return *this; +} + bool QgsFeatureRequest::acceptFeature( const QgsFeature& feature ) { switch ( mFilter ) diff --git a/src/core/qgsfeaturerequest.h b/src/core/qgsfeaturerequest.h index 203f63d81f6e..cebd5331eafe 100644 --- a/src/core/qgsfeaturerequest.h +++ b/src/core/qgsfeaturerequest.h @@ -20,6 +20,7 @@ #include "qgsfeature.h" #include "qgsrectangle.h" #include "qgsexpression.h" +#include "qgssimplifymethod.h" #include typedef QList QgsAttributeList; @@ -36,6 +37,7 @@ typedef QList QgsAttributeList; * For efficiency, it is also possible to tell provider that some data is not required: * - NoGeometry flag * - SubsetOfAttributes flag + * - SimplifyMethod for geometries to fetch * * The options may be chained, e.g.: * QgsFeatureRequest().setFilterRect(QgsRectangle(0,0,1,1)).setFlags(QgsFeatureRequest::ExactIntersect) @@ -120,6 +122,10 @@ class CORE_EXPORT QgsFeatureRequest //! Set a subset of attributes by names that will be fetched QgsFeatureRequest& setSubsetOfAttributes( const QStringList& attrNames, const QgsFields& fields ); + //! Set a simplification method for geometries that will be fetched + QgsFeatureRequest& setSimplifyMethod( const QgsSimplifyMethod& simplifyMethod ); + const QgsSimplifyMethod& simplifyMethod() const { return mSimplifyMethod; } + /** * Check if a feature is accepted by this requests filter * @@ -143,6 +149,7 @@ class CORE_EXPORT QgsFeatureRequest QgsExpression* mFilterExpression; Flags mFlags; QgsAttributeList mAttrs; + QgsSimplifyMethod mSimplifyMethod; }; Q_DECLARE_OPERATORS_FOR_FLAGS( QgsFeatureRequest::Flags ) diff --git a/src/core/qgssimplifymethod.cpp b/src/core/qgssimplifymethod.cpp new file mode 100644 index 000000000000..a2efeea73442 --- /dev/null +++ b/src/core/qgssimplifymethod.cpp @@ -0,0 +1,52 @@ +/*************************************************************************** + qgssimplifymethod.cpp + --------------------- + begin : December 2013 + copyright : (C) 2013 by Matthias Kuhn / Alvaro Huarte + email : + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgssimplifymethod.h" + +QgsSimplifyMethod::QgsSimplifyMethod() + : mMethodType( QgsSimplifyMethod::NoSimplification ) + , mTolerance( 1 ) + , mForceLocalOptimization( true ) +{ +} + +QgsSimplifyMethod::QgsSimplifyMethod( const QgsSimplifyMethod &rh ) +{ + operator=( rh ); +} + +QgsSimplifyMethod& QgsSimplifyMethod::operator=( const QgsSimplifyMethod &rh ) +{ + mMethodType = rh.mMethodType; + mTolerance = rh.mTolerance; + mForceLocalOptimization = rh.mForceLocalOptimization; + + return *this; +} + +void QgsSimplifyMethod::setMethodType( MethodType methodType ) +{ + mMethodType = methodType; +} + +void QgsSimplifyMethod::setTolerance( double tolerance ) +{ + mTolerance = tolerance; +} + +void QgsSimplifyMethod::setForceLocalOptimization( bool localOptimization ) +{ + mForceLocalOptimization = localOptimization; +} diff --git a/src/core/qgssimplifymethod.h b/src/core/qgssimplifymethod.h new file mode 100644 index 000000000000..276361445db2 --- /dev/null +++ b/src/core/qgssimplifymethod.h @@ -0,0 +1,63 @@ +/*************************************************************************** + qgssimplifymethod.h + --------------------- + begin : December 2013 + copyright : (C) 2013 by Matthias Kuhn / Alvaro Huarte + email : + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSSIMPLIFYMETHOD_H +#define QGSSIMPLIFYMETHOD_H + +/** + * This class contains information about how to simplify geometries fetched from a QgsFeatureIterator + */ +class CORE_EXPORT QgsSimplifyMethod +{ + public: + enum MethodType + { + NoSimplification, //!< No simplification is applied + OptimizeForRendering, //!< Simplify using the map2pixel data to optimize the rendering of geometries + PreserveTopology //!< Simplify using the Douglas-Peucker algorithm ensuring that the result is a valid geometry + }; + + //! construct a default method + QgsSimplifyMethod(); + //! copy constructor + QgsSimplifyMethod( const QgsSimplifyMethod& rh ); + //! assignment operator + QgsSimplifyMethod& operator=( const QgsSimplifyMethod& rh ); + + //! Sets the simplification type + void setMethodType( MethodType methodType ); + //! Gets the simplification type + inline MethodType methodType() const { return mMethodType; } + + //! Sets the tolerance of simplification. Represents the maximum distance between two coordinates which can be considered equal + void setTolerance( double tolerance ); + //! Gets the tolerance of simplification + inline double tolerance() const { return mTolerance; } + + //! Sets whether the simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries + void setForceLocalOptimization( bool localOptimization ); + //! Gets whether the simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries + inline bool forceLocalOptimization() const { return mForceLocalOptimization; } + + protected: + //! Simplification method + MethodType mMethodType; + //! Tolerance of simplification, it represents the maximum distance between two coordinates which can be considered equal + double mTolerance; + //! Simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries + bool mForceLocalOptimization; +}; + +#endif // QGSSIMPLIFYMETHOD_H From cf9e0db6e5cc0f20b38bd0dab019c0973649186f Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Tue, 24 Dec 2013 08:05:34 +0100 Subject: [PATCH 05/24] #8725-R: VectorLayer use SimplifyMethod VectorLayer define QgsVectorSimplifyMethod to configure the new QgsSimplifyMethod member of QgsFeatureRequest --- src/app/qgsoptions.cpp | 12 +- src/app/qgsvectorlayerproperties.cpp | 19 ++- src/core/qgsvectordataprovider.h | 2 + src/core/qgsvectorlayer.cpp | 136 +++++++++++------- src/core/qgsvectorlayer.h | 63 +++++--- .../symbology-ng/qgslinesymbollayerv2.cpp | 2 +- src/core/symbology-ng/qgssymbollayerv2.cpp | 2 +- src/ui/qgsoptionsbase.ui | 7 + src/ui/qgsvectorlayerpropertiesbase.ui | 7 + 9 files changed, 165 insertions(+), 85 deletions(-) diff --git a/src/app/qgsoptions.cpp b/src/app/qgsoptions.cpp index f1341ebfcac9..aceddc975a98 100644 --- a/src/app/qgsoptions.cpp +++ b/src/app/qgsoptions.cpp @@ -562,8 +562,9 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) : chkUseRenderCaching->setChecked( settings.value( "/qgis/enable_render_caching", false ).toBool() ); // Default simplify drawing configuration - mSimplifyDrawingGroupBox->setChecked( settings.value( "/qgis/simplifyDrawingHints", ( int )QgsVectorLayer::DefaultSimplification ).toInt() != QgsVectorLayer::NoSimplification ); + mSimplifyDrawingGroupBox->setChecked( settings.value( "/qgis/simplifyDrawingHints", ( int )QgsVectorLayer::GeometrySimplification ).toInt() != QgsVectorLayer::NoSimplification ); mSimplifyDrawingSlider->setValue(( int )( 5.0f * ( settings.value( "/qgis/simplifyDrawingTol", QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ).toFloat() - 1 ) ) ); + mSimplifyDrawingAtProvider->setChecked( !settings.value( "/qgis/simplifyLocal", true ).toBool() ); mSimplifyDrawingPanel->setVisible( mSimplifyDrawingSlider->value() > 0 ); mSimplifyDrawingPx->setText( QString( "(%1 px)" ).arg( 1.0f + 0.2f * mSimplifyDrawingSlider->value() ) ); @@ -1099,14 +1100,15 @@ void QgsOptions::saveOptions() settings.setValue( "/qgis/capitaliseLayerName", capitaliseCheckBox->isChecked() ); // Default simplify drawing configuration - int simplifyDrawingHints = QgsVectorLayer::NoSimplification; + int simplifyHints = QgsVectorLayer::NoSimplification; if ( mSimplifyDrawingGroupBox->isChecked() ) { - simplifyDrawingHints |= QgsVectorLayer::DefaultSimplification; - if ( mSimplifyDrawingSlider->value() > 0 ) simplifyDrawingHints |= QgsVectorLayer::AntialiasingSimplification; + simplifyHints |= QgsVectorLayer::GeometrySimplification; + if ( mSimplifyDrawingSlider->value() > 0 ) simplifyHints |= QgsVectorLayer::AntialiasingSimplification; } - settings.setValue( "/qgis/simplifyDrawingHints", simplifyDrawingHints ); + settings.setValue( "/qgis/simplifyDrawingHints", simplifyHints ); settings.setValue( "/qgis/simplifyDrawingTol", 1.0f + 0.2f*mSimplifyDrawingSlider->value() ); + settings.setValue( "/qgis/simplifyLocal", !mSimplifyDrawingAtProvider->isChecked() ); // project settings.setValue( "/qgis/projOpenAtLaunch", mProjectOnLaunchCmbBx->currentIndex() ); diff --git a/src/app/qgsvectorlayerproperties.cpp b/src/app/qgsvectorlayerproperties.cpp index 86ae538db263..1dda56e6f860 100644 --- a/src/app/qgsvectorlayerproperties.cpp +++ b/src/app/qgsvectorlayerproperties.cpp @@ -393,8 +393,10 @@ void QgsVectorLayerProperties::syncToLayer( void ) cbMaximumScale->setScale( 1.0 / layer->maximumScale() ); // get simplify drawing configuration - mSimplifyDrawingGroupBox->setChecked( layer->simplifyDrawingHints() != QgsVectorLayer::NoSimplification ); - mSimplifyDrawingSlider->setValue(( int )( 5.0f * ( layer->simplifyDrawingTol() - 1 ) ) ); + const QgsVectorSimplifyMethod& simplifyMethod = layer->simplifyMethod(); + mSimplifyDrawingGroupBox->setChecked( simplifyMethod.simplifyHints() != QgsVectorLayer::NoSimplification ); + mSimplifyDrawingSlider->setValue(( int )( 5.0f * ( simplifyMethod.threshold() - 1 ) ) ); + mSimplifyDrawingAtProvider->setChecked( !simplifyMethod.forceLocalOptimization() ); mSimplifyDrawingPanel->setVisible( mSimplifyDrawingSlider->value() > 0 ); mSimplifyDrawingPx->setText( QString( "(%1 px)" ).arg( 1.0f + 0.2f * mSimplifyDrawingSlider->value() ) ); @@ -536,14 +538,17 @@ void QgsVectorLayerProperties::apply() layer->setMetadataUrlFormat( mLayerMetadataUrlFormatComboBox->currentText() ); //layer simplify drawing configuration - int simplifyDrawingHints = QgsVectorLayer::NoSimplification; + int simplifyHints = QgsVectorLayer::NoSimplification; if ( mSimplifyDrawingGroupBox->isChecked() ) { - simplifyDrawingHints |= QgsVectorLayer::DefaultSimplification; - if ( mSimplifyDrawingSlider->value() > 0 ) simplifyDrawingHints |= QgsVectorLayer::AntialiasingSimplification; + simplifyHints |= QgsVectorLayer::GeometrySimplification; + if ( mSimplifyDrawingSlider->value() > 0 ) simplifyHints |= QgsVectorLayer::AntialiasingSimplification; } - layer->setSimplifyDrawingHints( simplifyDrawingHints ); - layer->setSimplifyDrawingTol( 1.0f + 0.2f*mSimplifyDrawingSlider->value() ); + QgsVectorSimplifyMethod simplifyMethod = layer->simplifyMethod(); + simplifyMethod.setSimplifyHints( simplifyHints ); + simplifyMethod.setThreshold( 1.0f + 0.2f*mSimplifyDrawingSlider->value() ); + simplifyMethod.setForceLocalOptimization( !mSimplifyDrawingAtProvider->isChecked() ); + layer->setSimplifyMethod( simplifyMethod ); // update symbology emit refreshLegend( layer->id(), QgsLegendItem::DontChange ); diff --git a/src/core/qgsvectordataprovider.h b/src/core/qgsvectordataprovider.h index 00ec22287ca4..1e41b3efd4d1 100644 --- a/src/core/qgsvectordataprovider.h +++ b/src/core/qgsvectordataprovider.h @@ -86,6 +86,8 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider CreateAttributeIndex = 1 << 12, /** allows user to select encoding */ SelectEncoding = 1 << 13, + /** supports simplification of geometries on provider side according to a distance tolerance */ + SimplifyGeometries = 1 << 14, }; /** bitmask of all provider's editing capabilities */ diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index 2a2812259616..317aeb4d7eb4 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -74,8 +74,7 @@ #include "qgsstylev2.h" #include "qgssymbologyv2conversion.h" #include "qgspallabeling.h" - -#include "qgsmaptopixelgeometrysimplifier.h" +#include "qgssimplifymethod.h" #include "diagram/qgsdiagram.h" @@ -123,8 +122,6 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath, , mProviderKey( providerKey ) , mReadOnly( false ) , mRendererV2( NULL ) - , mSimplifyDrawingTol( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ) - , mSimplifyDrawingHints( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD > 1 ? QgsVectorLayer::FullSimplification : QgsVectorLayer::DefaultSimplification ) , mLabel( 0 ) , mLabelOn( false ) , mLabelFontNotFoundNotified( false ) @@ -185,10 +182,11 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath, connect( QgsProject::instance()->relationManager(), SIGNAL( relationsLoaded() ), this, SLOT( onRelationsLoaded() ) ); - // Default simplify drawing configuration + // Default simplify drawing settings QSettings settings; - setSimplifyDrawingHints( settings.value( "/qgis/simplifyDrawingHints", ( int )mSimplifyDrawingHints ).toInt() ); - setSimplifyDrawingTol( settings.value( "/qgis/simplifyDrawingTol", mSimplifyDrawingTol ).toFloat() ); + mSimplifyMethod.setSimplifyHints( settings.value( "/qgis/simplifyDrawingHints", mSimplifyMethod.simplifyHints() ).toInt() ); + mSimplifyMethod.setThreshold( settings.value( "/qgis/simplifyDrawingTol", mSimplifyMethod.threshold() ).toFloat() ); + mSimplifyMethod.setForceLocalOptimization( settings.value( "/qgis/simplifyLocal", mSimplifyMethod.forceLocalOptimization() ).toBool() ); } // QgsVectorLayer ctor @@ -400,7 +398,7 @@ void QgsVectorLayer::drawLabels( QgsRenderContext& rendererContext ) -void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling, const QgsAbstractGeometrySimplifier* geometrySimplifier ) +void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling ) { if ( !hasGeometryType() ) return; @@ -451,13 +449,6 @@ void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& bool sel = mSelectedFeatureIds.contains( fet.id() ); bool drawMarker = ( mEditBuffer && ( !vertexMarkerOnlyForSelection || sel ) ); - // simplify the geometry using the current map2pixel context - if ( geometrySimplifier ) - { - fet = QgsFeature( fet ); - geometrySimplifier->simplifyGeometry( fet.geometry() ); - } - // render feature bool rendered = mRendererV2->renderFeature( fet, rendererContext, -1, sel, drawMarker ); @@ -500,7 +491,7 @@ void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& #endif } -void QgsVectorLayer::drawRendererV2Levels( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling, const QgsAbstractGeometrySimplifier* geometrySimplifier ) +void QgsVectorLayer::drawRendererV2Levels( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling ) { if ( !hasGeometryType() ) return; @@ -546,13 +537,6 @@ void QgsVectorLayer::drawRendererV2Levels( QgsFeatureIterator &fit, QgsRenderCon continue; } - // simplify the geometry using the current map2pixel context - if ( geometrySimplifier ) - { - fet = QgsFeature( fet ); - geometrySimplifier->simplifyGeometry( fet.geometry() ); - } - if ( !features.contains( sym ) ) { features.insert( sym, QList() ); @@ -712,38 +696,63 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext ) //do startRender before getFeatures to give renderers the possibility of querying features in the startRender method mRendererV2->startRender( rendererContext, this ); - QgsFeatureIterator fit = getFeatures( QgsFeatureRequest() - .setFilterRect( rendererContext.extent() ) - .setSubsetOfAttributes( attributes ) ); - - QgsAbstractGeometrySimplifier* geometrySimplifier = NULL; + QgsFeatureRequest& featureRequest = QgsFeatureRequest() + .setFilterRect( rendererContext.extent() ) + .setSubsetOfAttributes( attributes ); // enable the simplification of the geometries (Using the current map2pixel context) before send it to renderer engine. - if ( simplifyDrawingCanbeApplied( QgsVectorLayer::GeometrySimplification | QgsVectorLayer::EnvelopeSimplification ) ) + if ( simplifyDrawingCanbeApplied( QgsVectorLayer::GeometrySimplification ) ) { QPainter* p = rendererContext.painter(); - float dpi = ( p->device()->logicalDpiX() + p->device()->logicalDpiY() ) / 2; - float map2pixelTol = mSimplifyDrawingTol * 96.0f / dpi; + double dpi = ( p->device()->logicalDpiX() + p->device()->logicalDpiY() ) / 2; + double map2pixelTol = mSimplifyMethod.threshold() * 96.0f / dpi; + + const QgsMapToPixel& mtp = rendererContext.mapToPixel(); + map2pixelTol *= mtp.mapUnitsPerPixel(); + const QgsCoordinateTransform* ct = rendererContext.coordinateTransform(); + + // resize the tolerance using the change of size of an 1-BBOX from the source CoordinateSystem to the target CoordinateSystem + if ( ct && !(( QgsCoordinateTransform* )ct )->isShortCircuited() ) + { + QgsPoint center = rendererContext.extent().center(); + double rectSize = ct->sourceCrs().geographicFlag() ? 0.0008983 /* ~100/(40075014/360=111319.4833) */ : 100; + + QgsRectangle sourceRect = QgsRectangle( center.x(), center.y(), center.x() + rectSize, center.y() + rectSize ); + QgsRectangle targetRect = ct->transform( sourceRect ); + + QgsPoint minimumSrcPoint( sourceRect.xMinimum(), sourceRect.yMinimum() ); + QgsPoint maximumSrcPoint( sourceRect.xMaximum(), sourceRect.yMaximum() ); + QgsPoint minimumDstPoint( targetRect.xMinimum(), targetRect.yMinimum() ); + QgsPoint maximumDstPoint( targetRect.xMaximum(), targetRect.yMaximum() ); + + double sourceHypothenuse = sqrt( minimumSrcPoint.sqrDist( maximumSrcPoint ) ); + double targetHypothenuse = sqrt( minimumDstPoint.sqrDist( maximumDstPoint ) ); + + if ( sourceHypothenuse != 0 ) + map2pixelTol *= targetHypothenuse / sourceHypothenuse; + } - int simplifyFlags = QgsMapToPixelSimplifier::NoFlags; - if ( mSimplifyDrawingHints & QgsVectorLayer::GeometrySimplification ) simplifyFlags |= QgsMapToPixelSimplifier::SimplifyGeometry; - if ( mSimplifyDrawingHints & QgsVectorLayer::EnvelopeSimplification ) simplifyFlags |= QgsMapToPixelSimplifier::SimplifyEnvelope; + QgsSimplifyMethod simplifyMethod; + simplifyMethod.setMethodType( QgsSimplifyMethod::OptimizeForRendering ); + simplifyMethod.setTolerance( map2pixelTol ); + simplifyMethod.setForceLocalOptimization( mSimplifyMethod.forceLocalOptimization() ); - geometrySimplifier = - new QgsMapToPixelSimplifier( simplifyFlags, rendererContext.coordinateTransform(), &rendererContext.mapToPixel(), map2pixelTol ); + // fix simplification non supported on server side + if ( !simplifyMethod.forceLocalOptimization() && !( mDataProvider->capabilities() & QgsVectorDataProvider::SimplifyGeometries ) ) + { + QgsDebugMsg( "Data provider does not support geometry simplification on provider side" ); + simplifyMethod.setForceLocalOptimization( true ); + } + + featureRequest.setSimplifyMethod( simplifyMethod ); } + QgsFeatureIterator fit = getFeatures( featureRequest ); + if (( mRendererV2->capabilities() & QgsFeatureRendererV2::SymbolLevels ) && mRendererV2->usingSymbolLevels() ) - drawRendererV2Levels( fit, rendererContext, labeling, geometrySimplifier ); + drawRendererV2Levels( fit, rendererContext, labeling ); else - drawRendererV2( fit, rendererContext, labeling, geometrySimplifier ); - - // release the optional geometry simplifier - if ( geometrySimplifier ) - { - delete geometrySimplifier; - geometrySimplifier = NULL; - } + drawRendererV2( fit, rendererContext, labeling ); return true; } @@ -1256,7 +1265,7 @@ bool QgsVectorLayer::setSubsetString( QString subset ) bool QgsVectorLayer::simplifyDrawingCanbeApplied( int simplifyHint ) const { - return mDataProvider && ( mSimplifyDrawingHints & simplifyHint ) && !mEditBuffer && ( !mCurrentRendererContext || mCurrentRendererContext->useRenderingOptimization() ); + return mDataProvider && !mEditBuffer && ( mSimplifyMethod.simplifyHints() & simplifyHint ) && ( !mCurrentRendererContext || mCurrentRendererContext->useRenderingOptimization() ); } QgsFeatureIterator QgsVectorLayer::getFeatures( const QgsFeatureRequest& request ) @@ -1867,9 +1876,10 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage mLabel->setMinScale( e.attribute( "minLabelScale", "1" ).toFloat() ); mLabel->setMaxScale( e.attribute( "maxLabelScale", "100000000" ).toFloat() ); - // get the simplification drawing configuration - setSimplifyDrawingHints( e.attribute( "simplifyDrawingHints", "7" ).toInt() ); - setSimplifyDrawingTol( e.attribute( "simplifyDrawingTol", "1" ).toFloat() ); + // get the simplification drawing settings + mSimplifyMethod.setSimplifyHints( e.attribute( "simplifyDrawingHints", "1" ).toInt() ); + mSimplifyMethod.setThreshold( e.attribute( "simplifyDrawingTol", "1" ).toFloat() ); + mSimplifyMethod.setForceLocalOptimization( e.attribute( "simplifyLocal", "1" ).toInt() ); //also restore custom properties (for labeling-ng) readCustomProperties( node, "labeling" ); @@ -2204,9 +2214,10 @@ bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString& mapLayerNode.setAttribute( "minLabelScale", QString::number( mLabel->minScale() ) ); mapLayerNode.setAttribute( "maxLabelScale", QString::number( mLabel->maxScale() ) ); - // save the simplification drawing configuration - mapLayerNode.setAttribute( "simplifyDrawingHints", QString::number( mSimplifyDrawingHints ) ); - mapLayerNode.setAttribute( "simplifyDrawingTol", QString::number( mSimplifyDrawingTol ) ); + // save the simplification drawing settings + mapLayerNode.setAttribute( "simplifyDrawingHints", QString::number( mSimplifyMethod.simplifyHints() ) ); + mapLayerNode.setAttribute( "simplifyDrawingTol", QString::number( mSimplifyMethod.threshold() ) ); + mapLayerNode.setAttribute( "simplifyLocal", mSimplifyMethod.forceLocalOptimization() ? 1 : 0 ); //save customproperties (for labeling ng) writeCustomProperties( node, doc ); @@ -4206,3 +4217,24 @@ bool QgsAttributeEditorRelation::init( QgsRelationManager* relationManager ) mRelation = relationManager->relation( mRelationId ); return mRelation.isValid(); } + + +QgsVectorSimplifyMethod::QgsVectorSimplifyMethod() + : mSimplifyHints( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD > 1 ? QgsVectorLayer::FullSimplification : QgsVectorLayer::GeometrySimplification ) + , mThreshold( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ) + , mLocalOptimization( true ) +{ +} + +QgsVectorSimplifyMethod::QgsVectorSimplifyMethod( const QgsVectorSimplifyMethod &rh ) +{ + operator=( rh ); +} + +QgsVectorSimplifyMethod& QgsVectorSimplifyMethod::operator=( const QgsVectorSimplifyMethod &rh ) +{ + mSimplifyHints = rh.mSimplifyHints; + mThreshold = rh.mThreshold; + mLocalOptimization = rh.mLocalOptimization; + return *this; +} diff --git a/src/core/qgsvectorlayer.h b/src/core/qgsvectorlayer.h index de39c01d239b..c3ffdcc01013 100644 --- a/src/core/qgsvectorlayer.h +++ b/src/core/qgsvectorlayer.h @@ -179,6 +179,40 @@ struct CORE_EXPORT QgsVectorJoinInfo int joinFieldIndex; }; +/** This class contains information how to simplify geometries fetched from a vector layer */ +class CORE_EXPORT QgsVectorSimplifyMethod +{ + public: + //! construct a default object + QgsVectorSimplifyMethod(); + //! copy constructor + QgsVectorSimplifyMethod( const QgsVectorSimplifyMethod& rh ); + //! assignment operator + QgsVectorSimplifyMethod& operator=( const QgsVectorSimplifyMethod& rh ); + + /** Sets the simplification hints of the vector layer managed */ + void setSimplifyHints( int simplifyHints ) { mSimplifyHints = simplifyHints; } + /** Gets the simplification hints of the vector layer managed */ + inline int simplifyHints() const { return mSimplifyHints; } + + /** Sets the simplification threshold of the vector layer managed */ + void setThreshold( float threshold ) { mThreshold = threshold; } + /** Gets the simplification threshold of the vector layer managed */ + inline float threshold() const { return mThreshold; } + + /** Sets where the simplification executes, after fetch the geometries from provider, or when supported, in provider before fetch the geometries */ + void setForceLocalOptimization( bool localOptimization ) { mLocalOptimization = localOptimization; } + /** Gets where the simplification executes, after fetch the geometries from provider, or when supported, in provider before fetch the geometries */ + inline bool forceLocalOptimization() const { return mLocalOptimization; } + + private: + /** Simplification hints for fast rendering of features of the vector layer managed */ + int mSimplifyHints; + /** Simplification threshold */ + float mThreshold; + /** Simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries */ + bool mLocalOptimization; +}; /** \ingroup core * Represents a vector layer which manages a vector based data sets. @@ -730,12 +764,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer /** Draw layer with renderer V2. QgsFeatureRenderer::startRender() needs to be called before using this method * @note added in 1.4 */ - void drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling, const QgsAbstractGeometrySimplifier* geometrySimplifier = NULL ); + void drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling ); /** Draw layer with renderer V2 using symbol levels. QgsFeatureRenderer::startRender() needs to be called before using this method * @note added in 1.4 */ - void drawRendererV2Levels( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling, const QgsAbstractGeometrySimplifier* geometrySimplifier = NULL ); + void drawRendererV2Levels( QgsFeatureIterator &fit, QgsRenderContext& rendererContext, bool labeling ); /** Returns point, line or polygon */ QGis::GeometryType geometryType() const; @@ -1373,25 +1407,18 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer /** @note not available in python bindings */ inline QgsGeometryCache* cache() { return mCache; } - /** Set the Map2pixel simplification threshold for fast rendering of features */ - void setSimplifyDrawingTol( float simplifyDrawingTol ) { mSimplifyDrawingTol = simplifyDrawingTol; } - /** Returns the Map2pixel simplification threshold for fast rendering of features */ - float simplifyDrawingTol() const { return mSimplifyDrawingTol; } - /** Simplification flags for fast rendering of features */ enum SimplifyHint { NoSimplification = 0, //!< No simplification can be applied GeometrySimplification = 1, //!< The geometries can be simplified using the current map2pixel context state - EnvelopeSimplification = 2, //!< The geometries can be fully simplified by its BoundingBox using the current map2pixel context state - AntialiasingSimplification = 4, //!< The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size' - DefaultSimplification = 3, //!< Default simplification hints can be applied ( Geometry + Envelope ) - FullSimplification = 7, //!< All simplification hints can be applied ( Geometry + Envelope + AA-disabling ) + AntialiasingSimplification = 2, //!< The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size' + FullSimplification = 3, //!< All simplification hints can be applied ( Geometry + AA-disabling ) }; - /** Set the Map2pixel simplification hints for fast rendering of features */ - void setSimplifyDrawingHints( int simplifyDrawingHints ) { mSimplifyDrawingHints = simplifyDrawingHints; } - /** Returns the Map2pixel simplification hints for fast rendering of features */ - int simplifyDrawingHints() const { return mSimplifyDrawingHints; } + /** Set the simplification settings for fast rendering of features */ + void setSimplifyMethod( const QgsVectorSimplifyMethod& simplifyMethod ) { mSimplifyMethod = simplifyMethod; } + /** Returns the simplification settings for fast rendering of features */ + inline const QgsVectorSimplifyMethod& simplifyMethod() const { return mSimplifyMethod; } /** Returns whether the VectorLayer can apply the specified simplification hint */ bool simplifyDrawingCanbeApplied( int simplifyHint ) const; @@ -1665,10 +1692,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer /** Renderer object which holds the information about how to display the features */ QgsFeatureRendererV2 *mRendererV2; - /** Map2pixel geometry simplification threshold for fast rendering of features */ - float mSimplifyDrawingTol; - /** Map2pixel geometry simplification hints for fast rendering of features */ - int mSimplifyDrawingHints; + /** Simplification object which holds the information about how to simplify the features for fast rendering */ + QgsVectorSimplifyMethod mSimplifyMethod; /** Label */ QgsLabel *mLabel; diff --git a/src/core/symbology-ng/qgslinesymbollayerv2.cpp b/src/core/symbology-ng/qgslinesymbollayerv2.cpp index f5bb953ba2b6..53379b405af7 100644 --- a/src/core/symbology-ng/qgslinesymbollayerv2.cpp +++ b/src/core/symbology-ng/qgslinesymbollayerv2.cpp @@ -182,7 +182,7 @@ void QgsSimpleLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSym p->setPen( context.selected() ? mSelPen : mPen ); // Disable 'Antialiasing' if the geometry was generalized in the current RenderContext (We known that it must have least #2 points). - if ( points.size() <= 2 && context.layer() && context.layer()->simplifyDrawingCanbeApplied( QgsVectorLayer::AntialiasingSimplification ) && QgsAbstractGeometrySimplifier::canbeGeneralizedByDeviceBoundingBox( points, context.layer()->simplifyDrawingTol() ) && ( p->renderHints() & QPainter::Antialiasing ) ) + if ( points.size() <= 2 && context.layer() && context.layer()->simplifyDrawingCanbeApplied( QgsVectorLayer::AntialiasingSimplification ) && QgsAbstractGeometrySimplifier::canbeGeneralizedByDeviceBoundingBox( points, context.layer()->simplifyMethod().threshold() ) && ( p->renderHints() & QPainter::Antialiasing ) ) { p->setRenderHint( QPainter::Antialiasing, false ); p->drawPolyline( points ); diff --git a/src/core/symbology-ng/qgssymbollayerv2.cpp b/src/core/symbology-ng/qgssymbollayerv2.cpp index 8a3195f14035..81b9aa59ae51 100644 --- a/src/core/symbology-ng/qgssymbollayerv2.cpp +++ b/src/core/symbology-ng/qgssymbollayerv2.cpp @@ -385,7 +385,7 @@ void QgsFillSymbolLayerV2::_renderPolygon( QPainter* p, const QPolygonF& points, } // Disable 'Antialiasing' if the geometry was generalized in the current RenderContext (We known that it must have least #5 points). - if ( points.size() <= 5 && context.layer() && context.layer()->simplifyDrawingCanbeApplied( QgsVectorLayer::AntialiasingSimplification ) && QgsAbstractGeometrySimplifier::canbeGeneralizedByDeviceBoundingBox( points, context.layer()->simplifyDrawingTol() ) && ( p->renderHints() & QPainter::Antialiasing ) ) + if ( points.size() <= 5 && context.layer() && context.layer()->simplifyDrawingCanbeApplied( QgsVectorLayer::AntialiasingSimplification ) && QgsAbstractGeometrySimplifier::canbeGeneralizedByDeviceBoundingBox( points, context.layer()->simplifyMethod().threshold() ) && ( p->renderHints() & QPainter::Antialiasing ) ) { p->setRenderHint( QPainter::Antialiasing, false ); p->drawRect( points.boundingRect() ); diff --git a/src/ui/qgsoptionsbase.ui b/src/ui/qgsoptionsbase.ui index fb04a431a6b3..f90727a0c6b3 100644 --- a/src/ui/qgsoptionsbase.ui +++ b/src/ui/qgsoptionsbase.ui @@ -1713,6 +1713,13 @@ p, li { white-space: pre-wrap; } + + + + Simplification runs on provider side, otherwise it will execute once obtained the geometry from data source. + + + diff --git a/src/ui/qgsvectorlayerpropertiesbase.ui b/src/ui/qgsvectorlayerpropertiesbase.ui index 1eb9069bc31c..56b4ce512484 100644 --- a/src/ui/qgsvectorlayerpropertiesbase.ui +++ b/src/ui/qgsvectorlayerpropertiesbase.ui @@ -973,6 +973,13 @@ p, li { white-space: pre-wrap; } + + + + Simplification runs on provider side, otherwise it will execute once obtained the geometry from data source. + + + From 96f96ef97f8827d5c561e4839ad781193e86f971 Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Tue, 24 Dec 2013 08:20:50 +0100 Subject: [PATCH 06/24] #8725-R: FeatureIterator use SimplifyMethod AbstractFeatureIterator use SimplifyMethod to simplify locally the geometries fetched from data source (provider) --- src/core/qgsfeatureiterator.cpp | 52 ++++++++++++++++++-- src/core/qgsfeatureiterator.h | 5 ++ src/core/qgsmaptopixelgeometrysimplifier.cpp | 45 +++-------------- src/core/qgsmaptopixelgeometrysimplifier.h | 31 +++--------- 4 files changed, 68 insertions(+), 65 deletions(-) diff --git a/src/core/qgsfeatureiterator.cpp b/src/core/qgsfeatureiterator.cpp index b7cb622a2c29..54b15f7ac04c 100644 --- a/src/core/qgsfeatureiterator.cpp +++ b/src/core/qgsfeatureiterator.cpp @@ -15,33 +15,79 @@ #include "qgsfeatureiterator.h" #include "qgslogger.h" +#include "qgsgeometrysimplifier.h" +#include "qgsmaptopixelgeometrysimplifier.h" +#include "qgssimplifymethod.h" + QgsAbstractFeatureIterator::QgsAbstractFeatureIterator( const QgsFeatureRequest& request ) : mRequest( request ) , mClosed( false ) , refs( 0 ) + , mGeometrySimplifier( NULL ) { + const QgsSimplifyMethod& simplifyMethod = request.simplifyMethod(); + + if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && simplifyMethod.forceLocalOptimization() ) + { + QgsSimplifyMethod::MethodType methodType = simplifyMethod.methodType(); + + if ( methodType == QgsSimplifyMethod::OptimizeForRendering ) + { + int simplifyFlags = QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope; + mGeometrySimplifier = new QgsMapToPixelSimplifier( simplifyFlags, simplifyMethod.tolerance() ); + } + else + if ( methodType == QgsSimplifyMethod::PreserveTopology ) + { + mGeometrySimplifier = new QgsTopologyPreservingSimplifier( simplifyMethod.tolerance() ); + } + else + { + QgsDebugMsg( QString( "Simplification method type (%1) is not recognised" ).arg( methodType ) ); + } + } } QgsAbstractFeatureIterator::~QgsAbstractFeatureIterator() { + if ( mGeometrySimplifier ) + { + delete mGeometrySimplifier; + mGeometrySimplifier = NULL; + } } bool QgsAbstractFeatureIterator::nextFeature( QgsFeature& f ) { + bool dataOk = false; + switch ( mRequest.filterType() ) { case QgsFeatureRequest::FilterExpression: - return nextFeatureFilterExpression( f ); + dataOk = nextFeatureFilterExpression( f ); break; case QgsFeatureRequest::FilterFids: - return nextFeatureFilterFids( f ); + dataOk = nextFeatureFilterFids( f ); break; default: - return fetchFeature( f ); + dataOk = fetchFeature( f ); break; } + + // simplify locally the geometry using the simplifier defined in constructor + if ( dataOk && mGeometrySimplifier ) + { + QgsGeometry* geometry = f.geometry(); + + if ( geometry ) + { + QGis::GeometryType geometryType = geometry->type(); + if ( geometryType == QGis::Line || geometryType == QGis::Polygon ) mGeometrySimplifier->simplifyGeometry( geometry ); + } + } + return dataOk; } bool QgsAbstractFeatureIterator::nextFeatureFilterExpression( QgsFeature& f ) diff --git a/src/core/qgsfeatureiterator.h b/src/core/qgsfeatureiterator.h index 282e0a9bf4b3..433a8ad6d110 100644 --- a/src/core/qgsfeatureiterator.h +++ b/src/core/qgsfeatureiterator.h @@ -18,6 +18,7 @@ #include "qgsfeaturerequest.h" #include "qgslogger.h" +class QgsAbstractGeometrySimplifier; /** \ingroup core * Internal feature iterator to be implemented within data providers @@ -85,6 +86,10 @@ class CORE_EXPORT QgsAbstractFeatureIterator void ref(); //!< add reference void deref(); //!< remove reference, delete if refs == 0 friend class QgsFeatureIterator; + + private: + //! optional object to locally simplify geometries fetched by this feature iterator + QgsAbstractGeometrySimplifier* mGeometrySimplifier; }; diff --git a/src/core/qgsmaptopixelgeometrysimplifier.cpp b/src/core/qgsmaptopixelgeometrysimplifier.cpp index 962ebd86ac0d..0161f1b8cf5b 100644 --- a/src/core/qgsmaptopixelgeometrysimplifier.cpp +++ b/src/core/qgsmaptopixelgeometrysimplifier.cpp @@ -18,11 +18,9 @@ #include "qgsmaptopixelgeometrysimplifier.h" #include "qgsapplication.h" -QgsMapToPixelSimplifier::QgsMapToPixelSimplifier( int simplifyFlags, const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapTolPixel, float mapToPixelTol ) +QgsMapToPixelSimplifier::QgsMapToPixelSimplifier( int simplifyFlags, double map2pixelTol ) : mSimplifyFlags( simplifyFlags ) - , mMapCoordTransform( coordinateTransform ) - , mMapToPixel( mapTolPixel ) - , mMapToPixelTol( mapToPixelTol ) + , mMapToPixelTol( map2pixelTol ) { } QgsMapToPixelSimplifier::~QgsMapToPixelSimplifier() @@ -41,32 +39,6 @@ float QgsMapToPixelSimplifier::calculateLengthSquared2D( double x1, double y1, d return vx*vx + vy*vy; } -//! Returns the MapTolerance for transform between map coordinates and device coordinates -float QgsMapToPixelSimplifier::calculateViewPixelTolerance( const QgsRectangle& boundingRect, const QgsCoordinateTransform* ct, const QgsMapToPixel* mapToPixel ) -{ - double mapUnitsPerPixel = mapToPixel ? mapToPixel->mapUnitsPerPixel() : 1.0; - double mapUnitsFactor = 1; - - // Calculate one aprox factor of the size of the BBOX from the source CoordinateSystem to the target CoordinateSystem - if ( ct && !(( QgsCoordinateTransform* )ct )->isShortCircuited() ) - { - QgsRectangle sourceRect = boundingRect; - QgsRectangle targetRect = ct->transform( sourceRect ); - - QgsPoint minimumSrcPoint( sourceRect.xMinimum(), sourceRect.yMinimum() ); - QgsPoint maximumSrcPoint( sourceRect.xMaximum(), sourceRect.yMaximum() ); - QgsPoint minimumDstPoint( targetRect.xMinimum(), targetRect.yMinimum() ); - QgsPoint maximumDstPoint( targetRect.xMaximum(), targetRect.yMaximum() ); - - double sourceHypothenuse = sqrt( calculateLengthSquared2D( minimumSrcPoint.x(), minimumSrcPoint.y(), maximumSrcPoint.x(), maximumSrcPoint.y() ) ); - double targetHypothenuse = sqrt( calculateLengthSquared2D( minimumDstPoint.x(), minimumDstPoint.y(), maximumDstPoint.x(), maximumDstPoint.y() ) ); - - if ( targetHypothenuse != 0 ) - mapUnitsFactor = sourceHypothenuse / targetHypothenuse; - } - return ( float )( mapUnitsPerPixel * mapUnitsFactor ); -} - //! Returns the BBOX of the specified WKB-point stream inline static QgsRectangle calculateBoundingBox( QGis::WkbType wkbType, unsigned char* wkb, size_t numPoints ) { @@ -169,7 +141,7 @@ inline static bool generalizeWkbGeometry( QGis::WkbType wkbType, unsigned char* } //! Simplify the WKB-geometry using the specified tolerance -bool QgsMapToPixelSimplifier::simplifyWkbGeometry( int simplifyFlags, QGis::WkbType wkbType, unsigned char* sourceWkb, size_t sourceWkbSize, unsigned char* targetWkb, size_t& targetWkbSize, const QgsRectangle& envelope, float map2pixelTol, bool writeHeader, bool isaLinearRing ) +bool QgsMapToPixelSimplifier::simplifyWkbGeometry( int simplifyFlags, QGis::WkbType wkbType, unsigned char* sourceWkb, size_t sourceWkbSize, unsigned char* targetWkb, size_t& targetWkbSize, const QgsRectangle& envelope, double map2pixelTol, bool writeHeader, bool isaLinearRing ) { bool canbeGeneralizable = true; bool hasZValue = QGis::wkbDimensions( wkbType ) == 3; @@ -339,10 +311,8 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry( int simplifyFlags, QGis::WkbT ////////////////////////////////////////////////////////////////////////////////////////////// //! Returns whether the envelope can be replaced by its BBOX when is applied the specified map2pixel context -bool QgsMapToPixelSimplifier::canbeGeneralizedByMapBoundingBox( const QgsRectangle& envelope, const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapToPixel, float mapToPixelTol ) +bool QgsMapToPixelSimplifier::canbeGeneralizedByMapBoundingBox( const QgsRectangle& envelope, double map2pixelTol ) { - double map2pixelTol = mapToPixelTol * calculateViewPixelTolerance( envelope, coordinateTransform, mapToPixel ); - // Can replace the geometry by its BBOX ? if (( envelope.xMaximum() - envelope.xMinimum() ) < map2pixelTol && ( envelope.yMaximum() - envelope.yMinimum() ) < map2pixelTol ) { @@ -360,13 +330,13 @@ QgsGeometry* QgsMapToPixelSimplifier::simplify( QgsGeometry* geometry ) const unsigned char* wkb = ( unsigned char* )malloc( wkbSize ); memcpy( wkb, geometry->asWkb(), wkbSize ); g->fromWkb( wkb, wkbSize ); - simplifyGeometry( g, mSimplifyFlags, mMapCoordTransform, mMapToPixel, mMapToPixelTol ); + simplifyGeometry( g, mSimplifyFlags, mMapToPixelTol ); return g; } //! Simplifies the geometry (Removing duplicated points) when is applied the specified map2pixel context -bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry* geometry, int simplifyFlags, const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapToPixel, float mapToPixelTol ) +bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry* geometry, int simplifyFlags, double map2pixelTol ) { size_t targetWkbSize = 0; @@ -376,7 +346,6 @@ bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry* geometry, int simpl QgsRectangle envelope = geometry->boundingBox(); QGis::WkbType wkbType = geometry->wkbType(); - double map2pixelTol = mapToPixelTol * calculateViewPixelTolerance( envelope, coordinateTransform, mapToPixel ); unsigned char* wkb = ( unsigned char* )geometry->asWkb( ); size_t wkbSize = geometry->wkbSize( ); @@ -395,5 +364,5 @@ bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry* geometry, int simpl //! Simplifies the geometry (Removing duplicated points) when is applied the specified map2pixel context bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry* geometry ) const { - return simplifyGeometry( geometry, mSimplifyFlags, mMapCoordTransform, mMapToPixel, mMapToPixelTol ); + return simplifyGeometry( geometry, mSimplifyFlags, mMapToPixelTol ); } diff --git a/src/core/qgsmaptopixelgeometrysimplifier.h b/src/core/qgsmaptopixelgeometrysimplifier.h index 19e4735ad58b..dc1c5e12e3d7 100644 --- a/src/core/qgsmaptopixelgeometrysimplifier.h +++ b/src/core/qgsmaptopixelgeometrysimplifier.h @@ -32,7 +32,7 @@ class CORE_EXPORT QgsMapToPixelSimplifier : public QgsAbstractGeometrySimplifier { public: - QgsMapToPixelSimplifier( int simplifyFlags, const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapToPixel, float mapToPixelTol ); + QgsMapToPixelSimplifier( int simplifyFlags, double map2pixelTol ); virtual ~QgsMapToPixelSimplifier(); //! Applicable simplification flags @@ -45,37 +45,22 @@ class CORE_EXPORT QgsMapToPixelSimplifier : public QgsAbstractGeometrySimplifier private: //! Simplify the WKB-geometry using the specified tolerance - static bool simplifyWkbGeometry( int simplifyFlags, QGis::WkbType wkbType, unsigned char* sourceWkb, size_t sourceWkbSize, unsigned char* targetWkb, size_t& targetWkbSize, const QgsRectangle& envelope, float map2pixelTol, bool writeHeader = true, bool isaLinearRing = false ); + static bool simplifyWkbGeometry( int simplifyFlags, QGis::WkbType wkbType, unsigned char* sourceWkb, size_t sourceWkbSize, unsigned char* targetWkb, size_t& targetWkbSize, const QgsRectangle& envelope, double map2pixelTol, bool writeHeader = true, bool isaLinearRing = false ); protected: //! Current simplification flags int mSimplifyFlags; - //! For transformation between coordinate systems from current layer to map target. Can be 0 if on-the-fly reprojection is not used - const QgsCoordinateTransform* mMapCoordTransform; - //! For transformation between map coordinates and device coordinates - const QgsMapToPixel* mMapToPixel; - //! Factor tolterance to apply in transformation between map coordinates and device coordinates - float mMapToPixelTol; + //! Map2Pixel tolerance for the simplification + double mMapToPixelTol; //! Returns the squared 2D-distance of the vector defined by the two points specified static float calculateLengthSquared2D( double x1, double y1, double x2, double y2 ); - //! Returns the MapTolerance for transform between map coordinates and device coordinates - static float calculateViewPixelTolerance( const QgsRectangle& boundingRect, const QgsCoordinateTransform* ct, const QgsMapToPixel* mapToPixel ); public: int simplifyFlags() const { return mSimplifyFlags; } void setSimplifyFlags( int simplifyFlags ) { mSimplifyFlags = simplifyFlags; } - const QgsCoordinateTransform* coordinateTransform() const { return mMapCoordTransform; } - void setCoordinateTransform( const QgsCoordinateTransform* ct ) { mMapCoordTransform = ct; } - - const QgsMapToPixel* mapToPixel() const { return mMapToPixel; } - void setMapToPixel( const QgsMapToPixel* mtp ) { mMapToPixel = mtp; } - - float mapToPixelTol() const { return mMapToPixelTol; } - void setMapToPixelTol( float map2pixelTol ) { mMapToPixelTol = map2pixelTol; } - //! Returns a simplified version the specified geometry virtual QgsGeometry* simplify( QgsGeometry* geometry ) const; //! Simplifies the specified geometry @@ -85,15 +70,13 @@ class CORE_EXPORT QgsMapToPixelSimplifier : public QgsAbstractGeometrySimplifier public: //! Returns whether the envelope can be replaced by its BBOX when is applied the specified map2pixel context - static bool canbeGeneralizedByMapBoundingBox( const QgsRectangle& envelope, - const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapToPixel, float mapToPixelTol = 1.0f ); + static bool canbeGeneralizedByMapBoundingBox( const QgsRectangle& envelope, double map2pixelTol ); //! Returns whether the envelope can be replaced by its BBOX when is applied the specified map2pixel context - inline bool canbeGeneralizedByMapBoundingBox( const QgsRectangle& envelope ) const { return canbeGeneralizedByMapBoundingBox( envelope, mMapCoordTransform, mMapToPixel, mMapToPixelTol ); } + inline bool canbeGeneralizedByMapBoundingBox( const QgsRectangle& envelope ) const { return canbeGeneralizedByMapBoundingBox( envelope, mMapToPixelTol ); } //! Simplifies the geometry when is applied the specified map2pixel context - static bool simplifyGeometry( QgsGeometry* geometry, - int simplifyFlags, const QgsCoordinateTransform* coordinateTransform, const QgsMapToPixel* mapToPixel, float mapToPixelTol = 1.0f ); + static bool simplifyGeometry( QgsGeometry* geometry, int simplifyFlags, double map2pixelTol ); }; From c91eeabd8c4f32d387df3f6c72c9453ae83ecaaf Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Tue, 24 Dec 2013 12:03:06 +0100 Subject: [PATCH 07/24] #8725-R: move VectorSimplifyMethod to other file --- src/core/CMakeLists.txt | 1 + src/core/qgsvectorlayer.cpp | 21 ----------- src/core/qgsvectorlayer.h | 36 +------------------ src/core/qgsvectorsimplifymethod.cpp | 38 ++++++++++++++++++++ src/core/qgsvectorsimplifymethod.h | 54 ++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 56 deletions(-) create mode 100644 src/core/qgsvectorsimplifymethod.cpp create mode 100644 src/core/qgsvectorsimplifymethod.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9f78a8fb6aa4..0ec6116e0a11 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -130,6 +130,7 @@ SET(QGIS_CORE_SRCS qgsvectorlayerimport.cpp qgsvectorlayerjoinbuffer.cpp qgsvectorlayerundocommand.cpp + qgsvectorsimplifymethod.cpp qgsnetworkaccessmanager.cpp diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index 317aeb4d7eb4..25792e55fff1 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -4217,24 +4217,3 @@ bool QgsAttributeEditorRelation::init( QgsRelationManager* relationManager ) mRelation = relationManager->relation( mRelationId ); return mRelation.isValid(); } - - -QgsVectorSimplifyMethod::QgsVectorSimplifyMethod() - : mSimplifyHints( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD > 1 ? QgsVectorLayer::FullSimplification : QgsVectorLayer::GeometrySimplification ) - , mThreshold( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ) - , mLocalOptimization( true ) -{ -} - -QgsVectorSimplifyMethod::QgsVectorSimplifyMethod( const QgsVectorSimplifyMethod &rh ) -{ - operator=( rh ); -} - -QgsVectorSimplifyMethod& QgsVectorSimplifyMethod::operator=( const QgsVectorSimplifyMethod &rh ) -{ - mSimplifyHints = rh.mSimplifyHints; - mThreshold = rh.mThreshold; - mLocalOptimization = rh.mLocalOptimization; - return *this; -} diff --git a/src/core/qgsvectorlayer.h b/src/core/qgsvectorlayer.h index c3ffdcc01013..27d55e38e32c 100644 --- a/src/core/qgsvectorlayer.h +++ b/src/core/qgsvectorlayer.h @@ -32,6 +32,7 @@ #include "qgssnapper.h" #include "qgsfield.h" #include "qgsrelation.h" +#include "qgsvectorsimplifymethod.h" class QPainter; class QImage; @@ -179,41 +180,6 @@ struct CORE_EXPORT QgsVectorJoinInfo int joinFieldIndex; }; -/** This class contains information how to simplify geometries fetched from a vector layer */ -class CORE_EXPORT QgsVectorSimplifyMethod -{ - public: - //! construct a default object - QgsVectorSimplifyMethod(); - //! copy constructor - QgsVectorSimplifyMethod( const QgsVectorSimplifyMethod& rh ); - //! assignment operator - QgsVectorSimplifyMethod& operator=( const QgsVectorSimplifyMethod& rh ); - - /** Sets the simplification hints of the vector layer managed */ - void setSimplifyHints( int simplifyHints ) { mSimplifyHints = simplifyHints; } - /** Gets the simplification hints of the vector layer managed */ - inline int simplifyHints() const { return mSimplifyHints; } - - /** Sets the simplification threshold of the vector layer managed */ - void setThreshold( float threshold ) { mThreshold = threshold; } - /** Gets the simplification threshold of the vector layer managed */ - inline float threshold() const { return mThreshold; } - - /** Sets where the simplification executes, after fetch the geometries from provider, or when supported, in provider before fetch the geometries */ - void setForceLocalOptimization( bool localOptimization ) { mLocalOptimization = localOptimization; } - /** Gets where the simplification executes, after fetch the geometries from provider, or when supported, in provider before fetch the geometries */ - inline bool forceLocalOptimization() const { return mLocalOptimization; } - - private: - /** Simplification hints for fast rendering of features of the vector layer managed */ - int mSimplifyHints; - /** Simplification threshold */ - float mThreshold; - /** Simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries */ - bool mLocalOptimization; -}; - /** \ingroup core * Represents a vector layer which manages a vector based data sets. * diff --git a/src/core/qgsvectorsimplifymethod.cpp b/src/core/qgsvectorsimplifymethod.cpp new file mode 100644 index 000000000000..103fd376e155 --- /dev/null +++ b/src/core/qgsvectorsimplifymethod.cpp @@ -0,0 +1,38 @@ +/*************************************************************************** + qgsvectorsimplifymethod.cpp + --------------------- + begin : December 2013 + copyright : (C) 2013 by Alvaro Huarte + email : http://wiki.osgeo.org/wiki/Alvaro_Huarte + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgis.h" +#include "qgsvectorsimplifymethod.h" +#include "qgsvectorlayer.h" + +QgsVectorSimplifyMethod::QgsVectorSimplifyMethod() + : mSimplifyHints( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD > 1 ? QgsVectorLayer::FullSimplification : QgsVectorLayer::GeometrySimplification ) + , mThreshold( QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ) + , mLocalOptimization( true ) +{ +} + +QgsVectorSimplifyMethod::QgsVectorSimplifyMethod( const QgsVectorSimplifyMethod &rh ) +{ + operator=( rh ); +} + +QgsVectorSimplifyMethod& QgsVectorSimplifyMethod::operator=( const QgsVectorSimplifyMethod &rh ) +{ + mSimplifyHints = rh.mSimplifyHints; + mThreshold = rh.mThreshold; + mLocalOptimization = rh.mLocalOptimization; + return *this; +} diff --git a/src/core/qgsvectorsimplifymethod.h b/src/core/qgsvectorsimplifymethod.h new file mode 100644 index 000000000000..19673856d4a3 --- /dev/null +++ b/src/core/qgsvectorsimplifymethod.h @@ -0,0 +1,54 @@ +/*************************************************************************** + qgsvectorsimplifymethod.h + --------------------- + begin : December 2013 + copyright : (C) 2013 by Alvaro Huarte + email : http://wiki.osgeo.org/wiki/Alvaro_Huarte + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSVECTORSIMPLIFYMETHOD_H +#define QGSVECTORSIMPLIFYMETHOD_H + +/** This class contains information how to simplify geometries fetched from a vector layer */ +class CORE_EXPORT QgsVectorSimplifyMethod +{ + public: + //! construct a default object + QgsVectorSimplifyMethod(); + //! copy constructor + QgsVectorSimplifyMethod( const QgsVectorSimplifyMethod& rh ); + //! assignment operator + QgsVectorSimplifyMethod& operator=( const QgsVectorSimplifyMethod& rh ); + + /** Sets the simplification hints of the vector layer managed */ + void setSimplifyHints( int simplifyHints ) { mSimplifyHints = simplifyHints; } + /** Gets the simplification hints of the vector layer managed */ + inline int simplifyHints() const { return mSimplifyHints; } + + /** Sets the simplification threshold of the vector layer managed */ + void setThreshold( float threshold ) { mThreshold = threshold; } + /** Gets the simplification threshold of the vector layer managed */ + inline float threshold() const { return mThreshold; } + + /** Sets where the simplification executes, after fetch the geometries from provider, or when supported, in provider before fetch the geometries */ + void setForceLocalOptimization( bool localOptimization ) { mLocalOptimization = localOptimization; } + /** Gets where the simplification executes, after fetch the geometries from provider, or when supported, in provider before fetch the geometries */ + inline bool forceLocalOptimization() const { return mLocalOptimization; } + + private: + /** Simplification hints for fast rendering of features of the vector layer managed */ + int mSimplifyHints; + /** Simplification threshold */ + float mThreshold; + /** Simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries */ + bool mLocalOptimization; +}; + +#endif // QGSVECTORSIMPLIFYMETHOD_H From e9eb4768ab4a53e2c02972d76f20ba99d742d82c Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Fri, 27 Dec 2013 00:18:16 +0100 Subject: [PATCH 08/24] #8725-R: FeatureIterator and other minor changes --- src/app/qgsvectorlayerproperties.cpp | 25 +++++++++- src/app/qgsvectorlayerproperties.h | 1 + src/core/qgsfeatureiterator.cpp | 56 ++++++++++++++-------- src/core/qgsfeatureiterator.h | 3 ++ src/core/qgsgeometrysimplifier.h | 2 +- src/core/qgsvectordataprovider.cpp | 6 +++ src/core/qgsvectorlayerfeatureiterator.cpp | 3 ++ 7 files changed, 73 insertions(+), 23 deletions(-) diff --git a/src/app/qgsvectorlayerproperties.cpp b/src/app/qgsvectorlayerproperties.cpp index 1dda56e6f860..17e34d80c2cd 100644 --- a/src/app/qgsvectorlayerproperties.cpp +++ b/src/app/qgsvectorlayerproperties.cpp @@ -396,10 +396,21 @@ void QgsVectorLayerProperties::syncToLayer( void ) const QgsVectorSimplifyMethod& simplifyMethod = layer->simplifyMethod(); mSimplifyDrawingGroupBox->setChecked( simplifyMethod.simplifyHints() != QgsVectorLayer::NoSimplification ); mSimplifyDrawingSlider->setValue(( int )( 5.0f * ( simplifyMethod.threshold() - 1 ) ) ); - mSimplifyDrawingAtProvider->setChecked( !simplifyMethod.forceLocalOptimization() ); mSimplifyDrawingPanel->setVisible( mSimplifyDrawingSlider->value() > 0 ); mSimplifyDrawingPx->setText( QString( "(%1 px)" ).arg( 1.0f + 0.2f * mSimplifyDrawingSlider->value() ) ); + if ( !( layer->dataProvider()->capabilities() & QgsVectorDataProvider::SimplifyGeometries ) ) + { + mSimplifyDrawingAtProvider->setChecked( false ); + mSimplifyDrawingAtProvider->setEnabled( false ); + mSimplifyDrawingAtProvider->setText( QString( "%1 (%2)" ).arg( mSimplifyDrawingAtProvider->text(), tr( "Not supported" ) ) ); + } + else + { + mSimplifyDrawingAtProvider->setChecked( !simplifyMethod.forceLocalOptimization() ); + mSimplifyDrawingAtProvider->setEnabled( mSimplifyDrawingGroupBox->isChecked() ); + } + // load appropriate symbology page (V1 or V2) updateSymbologyPage(); @@ -1094,3 +1105,15 @@ void QgsVectorLayerProperties::on_mSimplifyDrawingSlider_valueChanged( int value mSimplifyDrawingPanel->setVisible( value > 0 ); mSimplifyDrawingPx->setText( QString( "(%1 px)" ).arg( 1.0f + 0.2f * value ) ); } + +void QgsVectorLayerProperties::on_mSimplifyDrawingGroupBox_toggled( bool checked ) +{ + if ( !( layer->dataProvider()->capabilities() & QgsVectorDataProvider::SimplifyGeometries ) ) + { + mSimplifyDrawingAtProvider->setEnabled( false ); + } + else + { + mSimplifyDrawingAtProvider->setEnabled( mSimplifyDrawingGroupBox->isChecked() ); + } +} diff --git a/src/app/qgsvectorlayerproperties.h b/src/app/qgsvectorlayerproperties.h index 5b022039a733..8df2d9af4784 100644 --- a/src/app/qgsvectorlayerproperties.h +++ b/src/app/qgsvectorlayerproperties.h @@ -120,6 +120,7 @@ class APP_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private void on_mMaximumScaleSetCurrentPushButton_clicked(); void on_mSimplifyDrawingSlider_valueChanged( int value ); + void on_mSimplifyDrawingGroupBox_toggled( bool checked ); signals: diff --git a/src/core/qgsfeatureiterator.cpp b/src/core/qgsfeatureiterator.cpp index 54b15f7ac04c..2d062e69fa40 100644 --- a/src/core/qgsfeatureiterator.cpp +++ b/src/core/qgsfeatureiterator.cpp @@ -25,27 +25,6 @@ QgsAbstractFeatureIterator::QgsAbstractFeatureIterator( const QgsFeatureRequest& , refs( 0 ) , mGeometrySimplifier( NULL ) { - const QgsSimplifyMethod& simplifyMethod = request.simplifyMethod(); - - if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && simplifyMethod.forceLocalOptimization() ) - { - QgsSimplifyMethod::MethodType methodType = simplifyMethod.methodType(); - - if ( methodType == QgsSimplifyMethod::OptimizeForRendering ) - { - int simplifyFlags = QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope; - mGeometrySimplifier = new QgsMapToPixelSimplifier( simplifyFlags, simplifyMethod.tolerance() ); - } - else - if ( methodType == QgsSimplifyMethod::PreserveTopology ) - { - mGeometrySimplifier = new QgsTopologyPreservingSimplifier( simplifyMethod.tolerance() ); - } - else - { - QgsDebugMsg( QString( "Simplification method type (%1) is not recognised" ).arg( methodType ) ); - } - } } QgsAbstractFeatureIterator::~QgsAbstractFeatureIterator() @@ -122,6 +101,41 @@ void QgsAbstractFeatureIterator::deref() delete this; } +bool QgsAbstractFeatureIterator::prepareLocalSimplification() +{ + const QgsSimplifyMethod& simplifyMethod = mRequest.simplifyMethod(); + + if ( mGeometrySimplifier ) + { + delete mGeometrySimplifier; + mGeometrySimplifier = NULL; + } + + // setup the local simplification of geometries to fetch, it uses the settings of current FeatureRequest + if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && simplifyMethod.forceLocalOptimization() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) + { + QgsSimplifyMethod::MethodType methodType = simplifyMethod.methodType(); + + if ( methodType == QgsSimplifyMethod::OptimizeForRendering ) + { + int simplifyFlags = QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope; + mGeometrySimplifier = new QgsMapToPixelSimplifier( simplifyFlags, simplifyMethod.tolerance() ); + return true; + } + else + if ( methodType == QgsSimplifyMethod::PreserveTopology ) + { + mGeometrySimplifier = new QgsTopologyPreservingSimplifier( simplifyMethod.tolerance() ); + return true; + } + else + { + QgsDebugMsg( QString( "Simplification method type (%1) is not recognised" ).arg( methodType ) ); + } + } + return false; +} + /////// QgsFeatureIterator& QgsFeatureIterator::operator=( const QgsFeatureIterator & other ) diff --git a/src/core/qgsfeatureiterator.h b/src/core/qgsfeatureiterator.h index 433a8ad6d110..b1692977b3a6 100644 --- a/src/core/qgsfeatureiterator.h +++ b/src/core/qgsfeatureiterator.h @@ -87,6 +87,9 @@ class CORE_EXPORT QgsAbstractFeatureIterator void deref(); //!< remove reference, delete if refs == 0 friend class QgsFeatureIterator; + //! setup if required the local simplification of geometries to fetch, it uses the settings of current FeatureRequest + virtual bool prepareLocalSimplification(); + private: //! optional object to locally simplify geometries fetched by this feature iterator QgsAbstractGeometrySimplifier* mGeometrySimplifier; diff --git a/src/core/qgsgeometrysimplifier.h b/src/core/qgsgeometrysimplifier.h index e6502e450f09..134ad36864fa 100644 --- a/src/core/qgsgeometrysimplifier.h +++ b/src/core/qgsgeometrysimplifier.h @@ -53,7 +53,7 @@ class CORE_EXPORT QgsTopologyPreservingSimplifier : public QgsAbstractGeometrySi QgsTopologyPreservingSimplifier( double tolerance ); virtual ~QgsTopologyPreservingSimplifier(); - private: + protected: //! Distance tolerance for the simplification double mTolerance; diff --git a/src/core/qgsvectordataprovider.cpp b/src/core/qgsvectordataprovider.cpp index 3ec4cba39e9d..614daa30fe8e 100644 --- a/src/core/qgsvectordataprovider.cpp +++ b/src/core/qgsvectordataprovider.cpp @@ -194,6 +194,12 @@ QString QgsVectorDataProvider::capabilitiesString() const QgsDebugMsg( "Capability: Change Geometries" ); } + if ( abilities & QgsVectorDataProvider::SimplifyGeometries ) + { + abilitiesList += tr( "Simplify Geometries" ); + QgsDebugMsg( "Capability: Simplify Geometries before fetch the feature" ); + } + return abilitiesList.join( ", " ); } diff --git a/src/core/qgsvectorlayerfeatureiterator.cpp b/src/core/qgsvectorlayerfeatureiterator.cpp index 731cdd137583..f4a76512466a 100644 --- a/src/core/qgsvectorlayerfeatureiterator.cpp +++ b/src/core/qgsvectorlayerfeatureiterator.cpp @@ -77,6 +77,9 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la mProviderIterator = L->dataProvider()->getFeatures( mProviderRequest ); } + // setup if required the local simplification of geometries to fetch + prepareLocalSimplification(); + rewindEditBuffer(); } From 40c14c9a3c99d056ac53caebff8138ff24c81dcb Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Fri, 27 Dec 2013 00:18:53 +0100 Subject: [PATCH 09/24] #8725-R: OgrProvider simplifies on provider side OgrFeatureIterator implements simplification on provider side --- src/providers/ogr/CMakeLists.txt | 2 +- src/providers/ogr/qgsogrfeatureiterator.cpp | 47 ++++ src/providers/ogr/qgsogrfeatureiterator.h | 8 + .../ogr/qgsogrgeometrysimplifier.cpp | 241 ++++++++++++++++++ src/providers/ogr/qgsogrgeometrysimplifier.h | 82 ++++++ src/providers/ogr/qgsogrprovider.cpp | 3 + 6 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 src/providers/ogr/qgsogrgeometrysimplifier.cpp create mode 100644 src/providers/ogr/qgsogrgeometrysimplifier.h diff --git a/src/providers/ogr/CMakeLists.txt b/src/providers/ogr/CMakeLists.txt index 710c1c3995b8..02d4901d0620 100644 --- a/src/providers/ogr/CMakeLists.txt +++ b/src/providers/ogr/CMakeLists.txt @@ -1,5 +1,5 @@ -SET (OGR_SRCS qgsogrprovider.cpp qgsogrdataitems.cpp qgsogrfeatureiterator.cpp) +SET (OGR_SRCS qgsogrprovider.cpp qgsogrdataitems.cpp qgsogrfeatureiterator.cpp qgsogrgeometrysimplifier.cpp) SET(OGR_MOC_HDRS qgsogrprovider.h qgsogrdataitems.h) diff --git a/src/providers/ogr/qgsogrfeatureiterator.cpp b/src/providers/ogr/qgsogrfeatureiterator.cpp index 86496bd59a23..835c21a20205 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.cpp +++ b/src/providers/ogr/qgsogrfeatureiterator.cpp @@ -15,6 +15,7 @@ #include "qgsogrfeatureiterator.h" #include "qgsogrprovider.h" +#include "qgsogrgeometrysimplifier.h" #include "qgsapplication.h" #include "qgsgeometry.h" @@ -38,6 +39,7 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrProvider* p, const QgsFeatur , ogrDataSource( 0 ) , ogrLayer( 0 ) , mSubsetStringSet( false ) + , mGeometrySimplifier( NULL ) { mFeatureFetched = false; @@ -78,12 +80,20 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrProvider* p, const QgsFeatur OGR_L_SetSpatialFilter( ogrLayer, 0 ); } + //setup if required the simplification of OGR-geometries fetched + prepareProviderSimplification(); + //start with first feature rewind(); } QgsOgrFeatureIterator::~QgsOgrFeatureIterator() { + if ( mGeometrySimplifier ) + { + delete mGeometrySimplifier; + mGeometrySimplifier = NULL; + } close(); } @@ -95,6 +105,40 @@ void QgsOgrFeatureIterator::ensureRelevantFields() P->mRelevantFieldsForNextFeature = true; } +bool QgsOgrFeatureIterator::prepareProviderSimplification() +{ + const QgsSimplifyMethod& simplifyMethod = mRequest.simplifyMethod(); + + if ( mGeometrySimplifier ) + { + delete mGeometrySimplifier; + mGeometrySimplifier = NULL; + } + + // setup if required the simplification of OGR-geometries fetched, it uses the settings of current FeatureRequest + if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !simplifyMethod.forceLocalOptimization() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) + { + QgsSimplifyMethod::MethodType methodType = simplifyMethod.methodType(); + + if ( methodType == QgsSimplifyMethod::OptimizeForRendering ) + { + int simplifyFlags = QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope; + mGeometrySimplifier = new QgsOgrMapToPixelSimplifier( simplifyFlags, simplifyMethod.tolerance() ); + return true; + } + else + if ( methodType == QgsSimplifyMethod::PreserveTopology ) + { + mGeometrySimplifier = new QgsOgrTopologyPreservingSimplifier( simplifyMethod.tolerance() ); + return true; + } + else + { + QgsDebugMsg( QString( "Simplification method type (%1) is not recognised by OgrFeatureIterator class" ).arg( methodType ) ); + } + } + return false; +} bool QgsOgrFeatureIterator::fetchFeature( QgsFeature& feature ) { @@ -233,6 +277,9 @@ bool QgsOgrFeatureIterator::readFeature( OGRFeatureH fet, QgsFeature& feature ) if ( geom ) { + OGRGeometry* ogrGeometry = (OGRGeometry*)geom; + if ( mGeometrySimplifier ) mGeometrySimplifier->simplifyGeometry( ogrGeometry ); + // get the wkb representation int memorySize = OGR_G_WkbSize( geom ); unsigned char *wkb = new unsigned char[memorySize]; diff --git a/src/providers/ogr/qgsogrfeatureiterator.h b/src/providers/ogr/qgsogrfeatureiterator.h index 0c1957fafbcf..43ee2cc233b9 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.h +++ b/src/providers/ogr/qgsogrfeatureiterator.h @@ -20,6 +20,7 @@ #include class QgsOgrProvider; +class QgsOgrAbstractGeometrySimplifier; class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator { @@ -38,6 +39,9 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator //! fetch next feature, return true on success virtual bool fetchFeature( QgsFeature& feature ); + //! setup if required the simplification of OGR-geometries fetched, it uses the settings of current FeatureRequest + virtual bool prepareProviderSimplification(); + QgsOgrProvider* P; void ensureRelevantFields(); @@ -56,6 +60,10 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator //! Set to true, if geometry is in the requested columns bool mFetchGeometry; + + private: + //! optional object to simplify OGR-geometries fecthed by this feature iterator + QgsOgrAbstractGeometrySimplifier* mGeometrySimplifier; }; #endif // QGSOGRFEATUREITERATOR_H diff --git a/src/providers/ogr/qgsogrgeometrysimplifier.cpp b/src/providers/ogr/qgsogrgeometrysimplifier.cpp new file mode 100644 index 000000000000..0b546767cebd --- /dev/null +++ b/src/providers/ogr/qgsogrgeometrysimplifier.cpp @@ -0,0 +1,241 @@ +/*************************************************************************** + qgsogrgeometrysimplifier.cpp + --------------------- + begin : December 2013 + copyright : (C) 2013 by Alvaro Huarte + email : http://wiki.osgeo.org/wiki/Alvaro_Huarte + + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgsogrgeometrysimplifier.h" +#include "qgsogrprovider.h" +#include "qgsapplication.h" + +QgsOgrAbstractGeometrySimplifier::~QgsOgrAbstractGeometrySimplifier() +{ +} + +/***************************************************************************/ + +QgsOgrTopologyPreservingSimplifier::QgsOgrTopologyPreservingSimplifier( double tolerance ) : QgsTopologyPreservingSimplifier( tolerance ) +{ +} + +QgsOgrTopologyPreservingSimplifier::~QgsOgrTopologyPreservingSimplifier() +{ +} + +//! Simplifies the specified geometry +bool QgsOgrTopologyPreservingSimplifier::simplifyGeometry( OGRGeometry* geometry ) +{ + OGRwkbGeometryType wkbGeometryType = QgsOgrProvider::ogrWkbSingleFlatten( geometry->getGeometryType() ); + + if ( wkbGeometryType == wkbLineString || wkbGeometryType == wkbPolygon ) + { + OGRGeometry* g = geometry->SimplifyPreserveTopology( mTolerance ); + + if ( g ) + { + size_t wkbSize = g->WkbSize(); + unsigned char * wkb = (unsigned char *)OGRMalloc( wkbSize ); + g->exportToWkb( ( OGRwkbByteOrder ) QgsApplication::endian(), wkb ); + geometry->importFromWkb( wkb, wkbSize ); + delete g; + + return true; + } + } + return false; +} + +/***************************************************************************/ + +QgsOgrMapToPixelSimplifier::QgsOgrMapToPixelSimplifier( int simplifyFlags, double map2pixelTol ) : QgsMapToPixelSimplifier( simplifyFlags, map2pixelTol ) +{ + mPointBufferCount = 64; + mPointBufferPtr = ( OGRRawPoint* )OGRMalloc( mPointBufferCount * sizeof( OGRRawPoint ) ); +} + +QgsOgrMapToPixelSimplifier::~QgsOgrMapToPixelSimplifier() +{ + if ( mPointBufferPtr ) + { + OGRFree( mPointBufferPtr ); + mPointBufferPtr = NULL; + } +} + +//! Returns a point buffer of the specified size +OGRRawPoint* QgsOgrMapToPixelSimplifier::mallocPoints( int numPoints ) +{ + if ( mPointBufferPtr && mPointBufferCount < numPoints ) + { + OGRFree( mPointBufferPtr ); + mPointBufferPtr = NULL; + } + if ( mPointBufferPtr == NULL ) + { + mPointBufferCount = numPoints; + mPointBufferPtr = ( OGRRawPoint* )OGRMalloc( mPointBufferCount * sizeof( OGRRawPoint ) ); + } + return mPointBufferPtr; +} + +////////////////////////////////////////////////////////////////////////////////////////////// +// Helper simplification methods + +//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context +bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( QGis::GeometryType geometryType, const QgsRectangle& envelope, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount ) +{ + bool canbeGeneralizable = ( mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyGeometry ); + + pointSimplifiedCount = pointCount; + if ( geometryType == QGis::Point || geometryType == QGis::UnknownGeometry ) return false; + pointSimplifiedCount = 0; + + double map2pixelTol = mMapToPixelTol * mMapToPixelTol; //-> Use mappixelTol for 'LengthSquare' calculations. + double x, y, lastX = 0, lastY = 0; + + char* xsourcePtr = ( char* )xptr; + char* ysourcePtr = ( char* )yptr; + char* xtargetPtr = ( char* )xptr; + char* ytargetPtr = ( char* )yptr; + + for ( int i = 0, numPoints = geometryType == QGis::Polygon ? pointCount - 1 : pointCount; i < numPoints; ++i ) + { + memcpy( &x, xsourcePtr, sizeof( double ) ); xsourcePtr += xStride; + memcpy( &y, ysourcePtr, sizeof( double ) ); ysourcePtr += yStride; + + if ( i == 0 || !canbeGeneralizable || QgsMapToPixelSimplifier::calculateLengthSquared2D( x, y, lastX, lastY ) > map2pixelTol ) + { + memcpy( xtargetPtr, &x, sizeof( double ) ); lastX = x; xtargetPtr += xStride; + memcpy( ytargetPtr, &y, sizeof( double ) ); lastY = y; ytargetPtr += yStride; + pointSimplifiedCount++; + } + } + if ( geometryType == QGis::Polygon ) + { + memcpy( xtargetPtr, xptr, sizeof( double ) ); + memcpy( ytargetPtr, yptr, sizeof( double ) ); + pointSimplifiedCount++; + } + return pointSimplifiedCount != pointCount; +} + +//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context +bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometry* geometry, bool isaLinearRing ) +{ + OGRwkbGeometryType wkbGeometryType = wkbFlatten( geometry->getGeometryType() ); + + // Simplify the geometry rewriting temporally its WKB-stream for saving calloc's. + if ( wkbGeometryType == wkbLineString ) + { + OGRLineString* lineString = ( OGRLineString* )geometry; + + int numPoints = lineString->getNumPoints(); + if (( isaLinearRing && numPoints <= 5 ) || ( !isaLinearRing && numPoints <= 2 ) ) return false; + + OGREnvelope env; + geometry->getEnvelope( &env ); + QgsRectangle envelope( env.MinX, env.MinY, env.MaxX, env.MaxY ); + + // Can replace the geometry by its BBOX ? + if (( mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyEnvelope ) && canbeGeneralizedByMapBoundingBox( envelope ) ) + { + OGRRawPoint* points = NULL; + int numPoints = 0; + + double x1 = envelope.xMinimum(); + double y1 = envelope.yMinimum(); + double x2 = envelope.xMaximum(); + double y2 = envelope.yMaximum(); + + if ( isaLinearRing ) + { + numPoints = 5; + points = mallocPoints( numPoints ); + points[0].x = x1; points[0].y = y1; + points[1].x = x2; points[1].y = y1; + points[2].x = x2; points[2].y = y2; + points[3].x = x1; points[3].y = y2; + points[4].x = x1; points[4].y = y1; + } + else + { + numPoints = 2; + points = mallocPoints( numPoints ); + points[0].x = x1; points[0].y = y1; + points[1].x = x2; points[1].y = y2; + } + lineString->setPoints( numPoints, points ); + lineString->flattenTo2D(); + return true; + } + else + if ( mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyGeometry ) + { + QGis::GeometryType geometryType = isaLinearRing ? QGis::Polygon : QGis::Line; + int numSimplifiedPoints = 0; + + OGRRawPoint* points = mallocPoints( numPoints ); + double* xptr = ( double* )points; + double* yptr = xptr + 1; + lineString->getPoints( points ); + + if ( simplifyOgrGeometry( geometryType, envelope, xptr, 16, yptr, 16, numPoints, numSimplifiedPoints ) ) + { + lineString->setPoints( numSimplifiedPoints, points ); + lineString->flattenTo2D(); + } + return numSimplifiedPoints != numPoints; + } + } + else + if ( wkbGeometryType == wkbPolygon ) + { + OGRPolygon* polygon = ( OGRPolygon* )geometry; + bool result = simplifyOgrGeometry( polygon->getExteriorRing(), true ); + + for ( int i = 0, numInteriorRings = polygon->getNumInteriorRings(); i < numInteriorRings; ++i ) + { + result |= simplifyOgrGeometry( polygon->getInteriorRing( i ), true ); + } + if ( result ) polygon->flattenTo2D(); + return result; + } + else + if ( wkbGeometryType == wkbMultiLineString || wkbGeometryType == wkbMultiPolygon ) + { + OGRGeometryCollection* collection = ( OGRGeometryCollection* )geometry; + bool result = false; + + for ( int i = 0, numGeometries = collection->getNumGeometries(); i < numGeometries; ++i ) + { + result |= simplifyOgrGeometry( collection->getGeometryRef( i ), wkbGeometryType == wkbMultiPolygon ); + } + if ( result ) collection->flattenTo2D(); + return result; + } + return false; +} + +////////////////////////////////////////////////////////////////////////////////////////////// + +//! Simplifies the specified geometry +bool QgsOgrMapToPixelSimplifier::simplifyGeometry( OGRGeometry* geometry ) +{ + OGRwkbGeometryType wkbGeometryType = QgsOgrProvider::ogrWkbSingleFlatten( geometry->getGeometryType() ); + + if ( wkbGeometryType == wkbLineString || wkbGeometryType == wkbPolygon ) + { + return simplifyOgrGeometry( geometry, wkbGeometryType == wkbPolygon ); + } + return false; +} diff --git a/src/providers/ogr/qgsogrgeometrysimplifier.h b/src/providers/ogr/qgsogrgeometrysimplifier.h new file mode 100644 index 000000000000..7a35cd3a6934 --- /dev/null +++ b/src/providers/ogr/qgsogrgeometrysimplifier.h @@ -0,0 +1,82 @@ +/*************************************************************************** + qgsogrgeometrysimplifier.h + --------------------- + begin : December 2013 + copyright : (C) 2013 by Alvaro Huarte + email : http://wiki.osgeo.org/wiki/Alvaro_Huarte + + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSOGRGEOMETRYSIMPLIFIER_H +#define QGSOGRGEOMETRYSIMPLIFIER_H + +#include "qgsmaptopixelgeometrysimplifier.h" +#include + +/** + * Abstract base class for simplify OGR-geometries using a specific algorithm + */ +class QgsOgrAbstractGeometrySimplifier +{ + public: + virtual ~QgsOgrAbstractGeometrySimplifier(); + + //! Simplifies the specified geometry + virtual bool simplifyGeometry( OGRGeometry* geometry ) = 0; +}; + +/** + * OGR Implementation of GeometrySimplifier using the Douglas-Peucker algorithm + * + * Simplifies a geometry, ensuring that the result is a valid geometry having the same dimension and number of components as the input. + * The simplification uses a maximum distance difference algorithm similar to the one used in the Douglas-Peucker algorithm. + */ +class QgsOgrTopologyPreservingSimplifier : public QgsOgrAbstractGeometrySimplifier, QgsTopologyPreservingSimplifier +{ + public: + QgsOgrTopologyPreservingSimplifier( double tolerance ); + virtual ~QgsOgrTopologyPreservingSimplifier(); + + //! Simplifies the specified geometry + virtual bool simplifyGeometry( OGRGeometry* geometry ); +}; + +/** + * OGR implementation of GeometrySimplifier using the "MapToPixel" algorithm + * + * Simplifies a geometry removing points within of the maximum distance difference that defines the MapToPixel info of a RenderContext request. + * This class enables simplify the geometries to be rendered in a MapCanvas target to speed up the vector drawing. + */ +class QgsOgrMapToPixelSimplifier : public QgsOgrAbstractGeometrySimplifier, QgsMapToPixelSimplifier +{ + public: + QgsOgrMapToPixelSimplifier( int simplifyFlags, double map2pixelTol ); + virtual ~QgsOgrMapToPixelSimplifier(); + + private: + //! Point memory buffer for optimize the simplification process + OGRRawPoint* mPointBufferPtr; + //! Current Point memory buffer size + int mPointBufferCount; + + //! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context + bool simplifyOgrGeometry( QGis::GeometryType geometryType, const QgsRectangle& envelope, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount ); + //! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context + bool simplifyOgrGeometry( OGRGeometry* geometry, bool isaLinearRing ); + + //! Returns a point buffer of the specified size + OGRRawPoint* mallocPoints( int numPoints ); + + public: + //! Simplifies the specified geometry + virtual bool simplifyGeometry( OGRGeometry* geometry ); +}; + +#endif // QGSOGRGEOMETRYSIMPLIFIER_H diff --git a/src/providers/ogr/qgsogrprovider.cpp b/src/providers/ogr/qgsogrprovider.cpp index 2b5faec0ebe9..f250708fbadd 100644 --- a/src/providers/ogr/qgsogrprovider.cpp +++ b/src/providers/ogr/qgsogrprovider.cpp @@ -1493,6 +1493,9 @@ int QgsOgrProvider::capabilities() const ability &= ~( AddAttributes | DeleteFeatures ); } } + + // supports geometry simplification on provider side + ability |= QgsVectorDataProvider::SimplifyGeometries; } return ability; From 9f229a8a34d2ea6fbbed2dd209479e709d3ea690 Mon Sep 17 00:00:00 2001 From: Alvaro Huarte Date: Fri, 27 Dec 2013 09:21:22 +0100 Subject: [PATCH 10/24] #8725-R: PostgresProvider simplifies on provider side PostgresFeatureIterator implements simplification on provider side --- .../postgres/qgspostgresfeatureiterator.cpp | 49 +++++++++++++++++++ .../postgres/qgspostgresfeatureiterator.h | 3 ++ .../postgres/qgspostgresprovider.cpp | 3 ++ 3 files changed, 55 insertions(+) diff --git a/src/providers/postgres/qgspostgresfeatureiterator.cpp b/src/providers/postgres/qgspostgresfeatureiterator.cpp index 6c088ab4452a..47054cb43d5a 100644 --- a/src/providers/postgres/qgspostgresfeatureiterator.cpp +++ b/src/providers/postgres/qgspostgresfeatureiterator.cpp @@ -80,6 +80,9 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresProvider* p, return; } + //setup if required the simplification of geometries to fetch + prepareProviderSimplification(); + mFetched = 0; } @@ -170,6 +173,26 @@ bool QgsPostgresFeatureIterator::fetchFeature( QgsFeature& feature ) return true; } +bool QgsPostgresFeatureIterator::prepareProviderSimplification() +{ + const QgsSimplifyMethod& simplifyMethod = mRequest.simplifyMethod(); + + // validate settings of simplification of geometries to fetch + if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !simplifyMethod.forceLocalOptimization() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) + { + QgsSimplifyMethod::MethodType methodType = simplifyMethod.methodType(); + + if ( methodType == QgsSimplifyMethod::OptimizeForRendering || methodType == QgsSimplifyMethod::PreserveTopology ) + { + return true; + } + else + { + QgsDebugMsg( QString( "Simplification method type (%1) is not recognised by PostgresFeatureIterator" ).arg( methodType ) ); + } + } + return false; +} bool QgsPostgresFeatureIterator::rewind() { @@ -272,8 +295,34 @@ bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause ) try { + const QgsSimplifyMethod& simplifyMethod = mRequest.simplifyMethod(); + QString query = "SELECT ", delim = ""; + if ( mFetchGeometry && !simplifyMethod.forceLocalOptimization() && simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification ) + { + QString simplifyFunctionName = simplifyMethod.methodType() == QgsSimplifyMethod::OptimizeForRendering + ? + ( P->mConnectionRO->majorVersion() < 2 ? "simplify" : "st_simplify" ) + : + ( P->mConnectionRO->majorVersion() < 2 ? "simplifypreservetopology" : "st_simplifypreservetopology" ); + + double tolerance = simplifyMethod.methodType() == QgsSimplifyMethod::OptimizeForRendering + ? + simplifyMethod.tolerance() / 5.0f /* experimental */ + : + simplifyMethod.tolerance(); + + query += QString( "%1(%5(%2%3,%6),'%4')" ) + .arg( P->mConnectionRO->majorVersion() < 2 ? "asbinary" : "st_asbinary" ) + .arg( P->quotedIdentifier( P->mGeometryColumn ) ) + .arg( P->mSpatialColType == sctGeography ? "::geometry" : "" ) + .arg( P->endianString() ) + .arg( simplifyFunctionName ) + .arg( tolerance ); + delim = ","; + } + else if ( mFetchGeometry ) { query += QString( "%1(%2%3,'%4')" ) diff --git a/src/providers/postgres/qgspostgresfeatureiterator.h b/src/providers/postgres/qgspostgresfeatureiterator.h index a69d63a9c368..b4ba18716d51 100644 --- a/src/providers/postgres/qgspostgresfeatureiterator.h +++ b/src/providers/postgres/qgspostgresfeatureiterator.h @@ -40,6 +40,9 @@ class QgsPostgresFeatureIterator : public QgsAbstractFeatureIterator //! fetch next feature, return true on success virtual bool fetchFeature( QgsFeature& feature ); + //! setup if required the simplification of geometries to fetch, it uses the settings of current FeatureRequest + virtual bool prepareProviderSimplification(); + QgsPostgresProvider* P; QString whereClauseRect(); diff --git a/src/providers/postgres/qgspostgresprovider.cpp b/src/providers/postgres/qgspostgresprovider.cpp index dd97bf14bb8a..a6d1574b3fad 100644 --- a/src/providers/postgres/qgspostgresprovider.cpp +++ b/src/providers/postgres/qgspostgresprovider.cpp @@ -993,6 +993,9 @@ bool QgsPostgresProvider::hasSufficientPermsAndCapabilities() } } + // supports geometry simplification on provider side + mEnabledCapabilities |= QgsVectorDataProvider::SimplifyGeometries; + return true; } From 2fa5c121bc22638b9b5026bdc2f89a53ff144e60 Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Sat, 28 Dec 2013 15:11:57 +0100 Subject: [PATCH 11/24] #8725-R: New vector provider capability for topological simplification --- src/core/qgsvectordataprovider.cpp | 6 ++++++ src/core/qgsvectordataprovider.h | 2 ++ src/providers/ogr/qgsogrprovider.cpp | 2 +- src/providers/postgres/qgspostgresprovider.cpp | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/core/qgsvectordataprovider.cpp b/src/core/qgsvectordataprovider.cpp index 614daa30fe8e..18326a5dde0e 100644 --- a/src/core/qgsvectordataprovider.cpp +++ b/src/core/qgsvectordataprovider.cpp @@ -200,6 +200,12 @@ QString QgsVectorDataProvider::capabilitiesString() const QgsDebugMsg( "Capability: Simplify Geometries before fetch the feature" ); } + if ( abilities & QgsVectorDataProvider::SimplifyGeometriesWithTopologicalValidation ) + { + abilitiesList += tr( "Simplify Geometries with topological validation" ); + QgsDebugMsg( "Capability: Simplify Geometries before fetch the feature ensuring that the result is a valid geometry" ); + } + return abilitiesList.join( ", " ); } diff --git a/src/core/qgsvectordataprovider.h b/src/core/qgsvectordataprovider.h index 1e41b3efd4d1..ae8f4db4a7fd 100644 --- a/src/core/qgsvectordataprovider.h +++ b/src/core/qgsvectordataprovider.h @@ -88,6 +88,8 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider SelectEncoding = 1 << 13, /** supports simplification of geometries on provider side according to a distance tolerance */ SimplifyGeometries = 1 << 14, + /** supports topological simplification of geometries on provider side according to a distance tolerance */ + SimplifyGeometriesWithTopologicalValidation = 1 << 15, }; /** bitmask of all provider's editing capabilities */ diff --git a/src/providers/ogr/qgsogrprovider.cpp b/src/providers/ogr/qgsogrprovider.cpp index f250708fbadd..f4dc6db739b8 100644 --- a/src/providers/ogr/qgsogrprovider.cpp +++ b/src/providers/ogr/qgsogrprovider.cpp @@ -1495,7 +1495,7 @@ int QgsOgrProvider::capabilities() const } // supports geometry simplification on provider side - ability |= QgsVectorDataProvider::SimplifyGeometries; + ability |= ( QgsVectorDataProvider::SimplifyGeometries | QgsVectorDataProvider::SimplifyGeometriesWithTopologicalValidation ); } return ability; diff --git a/src/providers/postgres/qgspostgresprovider.cpp b/src/providers/postgres/qgspostgresprovider.cpp index a6d1574b3fad..d13cbbfec12d 100644 --- a/src/providers/postgres/qgspostgresprovider.cpp +++ b/src/providers/postgres/qgspostgresprovider.cpp @@ -994,7 +994,7 @@ bool QgsPostgresProvider::hasSufficientPermsAndCapabilities() } // supports geometry simplification on provider side - mEnabledCapabilities |= QgsVectorDataProvider::SimplifyGeometries; + mEnabledCapabilities |= ( QgsVectorDataProvider::SimplifyGeometries | QgsVectorDataProvider::SimplifyGeometriesWithTopologicalValidation ); return true; } From 9d70f8c90372074b67b64d1a02efcd72f957a69f Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Sat, 28 Dec 2013 22:32:18 +0100 Subject: [PATCH 12/24] #8725-R: no simplify point layers in postgres provider --- src/providers/postgres/qgspostgresfeatureiterator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/providers/postgres/qgspostgresfeatureiterator.cpp b/src/providers/postgres/qgspostgresfeatureiterator.cpp index 47054cb43d5a..ca7093fcbbe8 100644 --- a/src/providers/postgres/qgspostgresfeatureiterator.cpp +++ b/src/providers/postgres/qgspostgresfeatureiterator.cpp @@ -299,7 +299,7 @@ bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause ) QString query = "SELECT ", delim = ""; - if ( mFetchGeometry && !simplifyMethod.forceLocalOptimization() && simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification ) + if ( mFetchGeometry && !simplifyMethod.forceLocalOptimization() && simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && QGis::flatType( QGis::singleType( P->geometryType() ) ) != QGis::WKBPoint ) { QString simplifyFunctionName = simplifyMethod.methodType() == QgsSimplifyMethod::OptimizeForRendering ? From aad758990a3052bd2539c868f5db6dcba13a9b83 Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Sat, 28 Dec 2013 22:56:44 +0100 Subject: [PATCH 13/24] #8725-R: never simplifying the first two or last two vertices in a line This ensure that the angles at the line start and end are the same after simplification --- src/core/qgsmaptopixelgeometrysimplifier.cpp | 2 +- src/providers/ogr/qgsogrgeometrysimplifier.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/qgsmaptopixelgeometrysimplifier.cpp b/src/core/qgsmaptopixelgeometrysimplifier.cpp index 0161f1b8cf5b..a5ff8b44b671 100644 --- a/src/core/qgsmaptopixelgeometrysimplifier.cpp +++ b/src/core/qgsmaptopixelgeometrysimplifier.cpp @@ -203,7 +203,7 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry( int simplifyFlags, QGis::WkbT memcpy( &x, sourceWkb, sizeof( double ) ); sourceWkb += sizeOfDoubleX; memcpy( &y, sourceWkb, sizeof( double ) ); sourceWkb += sizeOfDoubleY; - if ( i == 0 || !canbeGeneralizable || QgsMapToPixelSimplifier::calculateLengthSquared2D( x, y, lastX, lastY ) > map2pixelTol ) + if ( i == 0 || !canbeGeneralizable || QgsMapToPixelSimplifier::calculateLengthSquared2D( x, y, lastX, lastY ) > map2pixelTol || ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) ) { memcpy( ptr, &x, sizeof( double ) ); lastX = x; ptr++; memcpy( ptr, &y, sizeof( double ) ); lastY = y; ptr++; diff --git a/src/providers/ogr/qgsogrgeometrysimplifier.cpp b/src/providers/ogr/qgsogrgeometrysimplifier.cpp index 0b546767cebd..0e8925a4fac6 100644 --- a/src/providers/ogr/qgsogrgeometrysimplifier.cpp +++ b/src/providers/ogr/qgsogrgeometrysimplifier.cpp @@ -113,7 +113,7 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( QGis::GeometryType geometr memcpy( &x, xsourcePtr, sizeof( double ) ); xsourcePtr += xStride; memcpy( &y, ysourcePtr, sizeof( double ) ); ysourcePtr += yStride; - if ( i == 0 || !canbeGeneralizable || QgsMapToPixelSimplifier::calculateLengthSquared2D( x, y, lastX, lastY ) > map2pixelTol ) + if ( i == 0 || !canbeGeneralizable || QgsMapToPixelSimplifier::calculateLengthSquared2D( x, y, lastX, lastY ) > map2pixelTol || ( geometryType == QGis::Line && ( i == 1 || i >= numPoints - 2 ) ) ) { memcpy( xtargetPtr, &x, sizeof( double ) ); lastX = x; xtargetPtr += xStride; memcpy( ytargetPtr, &y, sizeof( double ) ); lastY = y; ytargetPtr += yStride; @@ -140,7 +140,7 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometry* geometry, boo OGRLineString* lineString = ( OGRLineString* )geometry; int numPoints = lineString->getNumPoints(); - if (( isaLinearRing && numPoints <= 5 ) || ( !isaLinearRing && numPoints <= 2 ) ) return false; + if (( isaLinearRing && numPoints <= 5 ) || ( !isaLinearRing && numPoints <= 4 ) ) return false; OGREnvelope env; geometry->getEnvelope( &env ); From da364613edaede310096751514eba9f7b929b9b9 Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Mon, 6 Jan 2014 22:54:07 +0100 Subject: [PATCH 14/24] #8725-R: include qgsvectorsimplifymethod.sip --- python/core/core.sip | 1 + python/core/qgsvectorlayer.sip | 19 +++++----------- python/core/qgsvectorsimplifymethod.sip | 29 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 13 deletions(-) create mode 100644 python/core/qgsvectorsimplifymethod.sip diff --git a/python/core/core.sip b/python/core/core.sip index e958e9268438..aca5927372c7 100644 --- a/python/core/core.sip +++ b/python/core/core.sip @@ -86,6 +86,7 @@ %Include qgsvectorlayerimport.sip %Include qgsvectorlayerjoinbuffer.sip %Include qgsvectorlayerundocommand.sip +%Include qgsvectorsimplifymethod.sip %Include qgsfontutils.sip %Include qgscachedfeatureiterator.sip diff --git a/python/core/qgsvectorlayer.sip b/python/core/qgsvectorlayer.sip index a159ecb2f3e9..1bd1acf1a1be 100644 --- a/python/core/qgsvectorlayer.sip +++ b/python/core/qgsvectorlayer.sip @@ -999,25 +999,18 @@ class QgsVectorLayer : QgsMapLayer /** @note not available in python bindings */ // inline QgsGeometryCache* cache(); - /** Set the Map2pixel simplification threshold for fast rendering of features */ - void setSimplifyDrawingTol( float simplifyDrawingTol ); - /** Returns the Map2pixel simplification threshold for fast rendering of features */ - float simplifyDrawingTol() const; - /** Simplification flags for fast rendering of features */ enum SimplifyHint { NoSimplification = 0, //!< No simplification can be applied GeometrySimplification = 1, //!< The geometries can be simplified using the current map2pixel context state - EnvelopeSimplification = 2, //!< The geometries can be fully simplified by its BoundingBox using the current map2pixel context state - AntialiasingSimplification = 4, //!< The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size' - DefaultSimplification = 3, //!< Default simplification hints can be applied ( Geometry + Envelope ) - FullSimplification = 7, //!< All simplification hints can be applied ( Geometry + Envelope + AA-disabling ) + AntialiasingSimplification = 2, //!< The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size' + FullSimplification = 3, //!< All simplification hints can be applied ( Geometry + AA-disabling ) }; - /** Set the Map2pixel simplification hints for fast rendering of features */ - void setSimplifyDrawingHints( int simplifyDrawingHints ); - /** Returns the Map2pixel simplification hints for fast rendering of features */ - int simplifyDrawingHints() const; + /** Set the simplification settings for fast rendering of features */ + void setSimplifyMethod( const QgsVectorSimplifyMethod& simplifyMethod ); + /** Returns the simplification settings for fast rendering of features */ + const QgsVectorSimplifyMethod& simplifyMethod() const; /** Returns whether the VectorLayer can apply the specified simplification hint */ bool simplifyDrawingCanbeApplied( int simplifyHint ) const; diff --git a/python/core/qgsvectorsimplifymethod.sip b/python/core/qgsvectorsimplifymethod.sip new file mode 100644 index 000000000000..61a4ef665fa3 --- /dev/null +++ b/python/core/qgsvectorsimplifymethod.sip @@ -0,0 +1,29 @@ + +/** This class contains information how to simplify geometries fetched from a vector layer */ +class QgsVectorSimplifyMethod +{ +%TypeHeaderCode +#include "qgsvectorsimplifymethod.h" +%End + + public: + //! construct a default object + QgsVectorSimplifyMethod(); + //! copy constructor + QgsVectorSimplifyMethod( const QgsVectorSimplifyMethod& rh ); + + /** Sets the simplification hints of the vector layer managed */ + void setSimplifyHints( int simplifyHints ); + /** Gets the simplification hints of the vector layer managed */ + int simplifyHints() const; + + /** Sets the simplification threshold of the vector layer managed */ + void setThreshold( float threshold ); + /** Gets the simplification threshold of the vector layer managed */ + float threshold() const; + + /** Sets where the simplification executes, after fetch the geometries from provider, or when supported, in provider before fetch the geometries */ + void setForceLocalOptimization( bool localOptimization ); + /** Gets where the simplification executes, after fetch the geometries from provider, or when supported, in provider before fetch the geometries */ + bool forceLocalOptimization(); +}; From 500dfcf857bec4a5eca838e37a48ab4f75c52c06 Mon Sep 17 00:00:00 2001 From: Alvaro Huarte Date: Tue, 7 Jan 2014 11:10:40 +0100 Subject: [PATCH 15/24] #8725-R: add "Advanced settings" panel --- src/ui/qgsoptionsbase.ui | 384 +++++++++++++------------ src/ui/qgsvectorlayerpropertiesbase.ui | 314 ++++++++++---------- 2 files changed, 367 insertions(+), 331 deletions(-) diff --git a/src/ui/qgsoptionsbase.ui b/src/ui/qgsoptionsbase.ui index f90727a0c6b3..a9b7772d4fbe 100644 --- a/src/ui/qgsoptionsbase.ui +++ b/src/ui/qgsoptionsbase.ui @@ -1681,199 +1681,217 @@ - - - - Simplify geometries by default - - - true - - - - - - - 0 - 0 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + + Simplify geometries by default + + + true + + + + + + + 0 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If checked, new vector layers added to the map will automatically use geometry simplification to speed up rendering. The simplification applies only during rendering of the layer and does not modify the layer geometry.</p></body></html> - - - true - - - 2 - - - - - - - Simplification runs on provider side, otherwise it will execute once obtained the geometry from data source. - - - - - - - Simplification threshold (higher values result in more simplification): - - - 2 - - - - - - - - 130 - 16777215 - - - - Higher values result in more simplification - - - 0 - - - 20 - - - 0 - - - true - - - Qt::Horizontal - - - false - - - false - - - - - - - (0 px) - - - 2 - - - - - - - - 0 - 70 - - - - - 16777215 - 16777215 - - - - QFrame::Box - - - QFrame::Raised - - - - - 10 - 0 - 60 - 67 - - - - - 0 - 0 - - - - - 60 - 67 - - - - - 40 - 40 - - - - Qt::LeftToRight - - - false - - - - - - :/images/themes/default/mIconWarn.png - - - false - - - - - - 45 - 8 - 411 - 51 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + true + + + 2 + + + + + + + Advanced settings + + + vectormeta + + + + + + Simplification runs on provider side, otherwise it will execute once obtained the geometry from data source. + + + + + + + Simplification threshold (higher values result in more simplification): + + + 2 + + + + + + + + 130 + 16777215 + + + + + 130 + 16777215 + + + + Higher values result in more simplification + + + 0 + + + 20 + + + 0 + + + true + + + Qt::Horizontal + + + false + + + false + + + + + + + (0 px) + + + 2 + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + + 0 + 70 + + + + + 16777215 + 16777215 + + + + QFrame::Box + + + QFrame::Raised + + + + + 10 + 0 + 60 + 67 + + + + + 0 + 0 + + + + + 60 + 67 + + + + + 40 + 40 + + + + Qt::LeftToRight + + + false + + + + + + :/images/themes/default/mIconWarn.png + + + false + + + + + + 45 + 8 + 411 + 51 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><span style=" font-size:8pt; font-weight:600;">Warning:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> Increasing this threshold may speed up rendering, but may result in gaps </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> or topological errors in the layer display.</span></p></body></html> - - - - - - - - Qt::Horizontal - - - - 20 - 20 - - - - - - - + + + + + + + + + + diff --git a/src/ui/qgsvectorlayerpropertiesbase.ui b/src/ui/qgsvectorlayerpropertiesbase.ui index 56b4ce512484..067052b82597 100644 --- a/src/ui/qgsvectorlayerpropertiesbase.ui +++ b/src/ui/qgsvectorlayerpropertiesbase.ui @@ -974,163 +974,181 @@ p, li { white-space: pre-wrap; } - - - Simplification runs on provider side, otherwise it will execute once obtained the geometry from data source. - - - - - - - Simplification threshold (higher values result in more simplification): + + + Advanced settings - - 2 - - - - - - - - 130 - 16777215 - - - - Higher values result in more simplification - - - 0 - - - 20 - - - 0 - - - true - - - Qt::Horizontal - - - false + + vectormeta - - false - - - - - - - (0 px) - - - 2 - - - - - - - - 0 - 70 - - - - - 16777215 - 16777215 - - - - QFrame::Box - - - QFrame::Raised - - - - - 10 - 0 - 60 - 67 - - - - - 0 - 0 - - - - - 60 - 67 - - - - - 40 - 40 - - - - Qt::LeftToRight - - - false - - - - - - :/images/themes/default/mIconWarn.png - - - false - - - - - - 45 - 8 - 411 - 51 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + + + + + Simplification runs on provider side, otherwise it will execute once obtained the geometry from data source. + + + + + + + Simplification threshold (higher values result in more simplification): + + + 2 + + + + + + + + 130 + 16777215 + + + + + 130 + 16777215 + + + + Higher values result in more simplification + + + 0 + + + 20 + + + 0 + + + true + + + Qt::Horizontal + + + false + + + false + + + + + + + (0 px) + + + 2 + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + + 0 + 70 + + + + + 16777215 + 16777215 + + + + QFrame::Box + + + QFrame::Raised + + + + + 10 + 0 + 60 + 67 + + + + + 0 + 0 + + + + + 60 + 67 + + + + + 40 + 40 + + + + Qt::LeftToRight + + + false + + + + + + :/images/themes/default/mIconWarn.png + + + false + + + + + + 45 + 8 + 411 + 51 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><span style=" font-size:8pt; font-weight:600;">Warning:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> Increasing this threshold may speed up rendering, but may result in gaps </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> or topological errors in the layer display.</span></p></body></html> - - + + + + + - - - - - Qt::Horizontal - - - - 20 - 20 - - - - + From c07e7cfc17dd75903a4cd1cca9f1f2328fcf8eba Mon Sep 17 00:00:00 2001 From: Alvaro Huarte Date: Tue, 7 Jan 2014 13:41:51 +0100 Subject: [PATCH 16/24] #8725-R: fix old API in testqgsblendmodes.cpp --- tests/src/core/testqgsblendmodes.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/src/core/testqgsblendmodes.cpp b/tests/src/core/testqgsblendmodes.cpp index 483caa09b36c..9a75135d5d65 100644 --- a/tests/src/core/testqgsblendmodes.cpp +++ b/tests/src/core/testqgsblendmodes.cpp @@ -85,7 +85,11 @@ void TestQgsBlendModes::initTestCase() QFileInfo myPolyFileInfo( myPolysFileName ); mpPolysLayer = new QgsVectorLayer( myPolyFileInfo.filePath(), myPolyFileInfo.completeBaseName(), "ogr" ); - mpPolysLayer->setSimplifyDrawingHints( QgsVectorLayer::NoSimplification ); + + QgsVectorSimplifyMethod simplifyMethod; + simplifyMethod.setSimplifyHints( QgsVectorLayer::NoSimplification ); + + mpPolysLayer->setSimplifyMethod( simplifyMethod ); QgsMapLayerRegistry::instance()->addMapLayers( QList() << mpPolysLayer ); @@ -94,7 +98,7 @@ void TestQgsBlendModes::initTestCase() QFileInfo myLineFileInfo( myLinesFileName ); mpLinesLayer = new QgsVectorLayer( myLineFileInfo.filePath(), myLineFileInfo.completeBaseName(), "ogr" ); - mpLinesLayer->setSimplifyDrawingHints( QgsVectorLayer::NoSimplification ); + mpLinesLayer->setSimplifyMethod( simplifyMethod ); QgsMapLayerRegistry::instance()->addMapLayers( QList() << mpLinesLayer ); From bc6c77abf05e6aa8b28efc48946367ed80df496c Mon Sep 17 00:00:00 2001 From: Alvaro Huarte Date: Tue, 7 Jan 2014 13:59:14 +0100 Subject: [PATCH 17/24] #8725-R: fix old API in other test cpp files --- tests/src/core/testqgsatlascomposition.cpp | 4 +++- tests/src/core/testqgsgradients.cpp | 10 ++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/src/core/testqgsatlascomposition.cpp b/tests/src/core/testqgsatlascomposition.cpp index 8e5cbcf4aeba..5732b23c6e57 100644 --- a/tests/src/core/testqgsatlascomposition.cpp +++ b/tests/src/core/testqgsatlascomposition.cpp @@ -80,7 +80,9 @@ void TestQgsAtlasComposition::initTestCase() vectorFileInfo.completeBaseName(), "ogr" ); - mVectorLayer->setSimplifyDrawingHints( QgsVectorLayer::NoSimplification ); + QgsVectorSimplifyMethod simplifyMethod; + simplifyMethod.setSimplifyHints( QgsVectorLayer::NoSimplification ); + mVectorLayer->setSimplifyMethod( simplifyMethod ); QgsMapLayerRegistry::instance()->addMapLayers( QList() << mVectorLayer ); diff --git a/tests/src/core/testqgsgradients.cpp b/tests/src/core/testqgsgradients.cpp index 19cb2edf7092..1e56b564fa4a 100644 --- a/tests/src/core/testqgsgradients.cpp +++ b/tests/src/core/testqgsgradients.cpp @@ -94,7 +94,11 @@ void TestQgsGradients::initTestCase() QFileInfo myPolyFileInfo( myPolysFileName ); mpPolysLayer = new QgsVectorLayer( myPolyFileInfo.filePath(), myPolyFileInfo.completeBaseName(), "ogr" ); - mpPolysLayer->setSimplifyDrawingHints( QgsVectorLayer::NoSimplification ); + + QgsVectorSimplifyMethod simplifyMethod; + simplifyMethod.setSimplifyHints( QgsVectorLayer::NoSimplification ); + mpPolysLayer->setSimplifyMethod( simplifyMethod ); + // Register the layer with the registry QgsMapLayerRegistry::instance()->addMapLayers( QList() << mpPolysLayer ); @@ -245,7 +249,9 @@ void TestQgsGradients::gradientSymbolFromQml() { mReport += "

Gradient symbol from QML test

\n"; QVERIFY( setQml( "gradient" ) ); - mpPolysLayer->setSimplifyDrawingHints( QgsVectorLayer::NoSimplification ); + QgsVectorSimplifyMethod simplifyMethod; + simplifyMethod.setSimplifyHints( QgsVectorLayer::NoSimplification ); + mpPolysLayer->setSimplifyMethod( simplifyMethod ); QVERIFY( imageCheck( "gradient_from_qml" ) ); } From e22279fc30e3921e559d8d624902276114c00acf Mon Sep 17 00:00:00 2001 From: Alvaro Huarte Date: Wed, 8 Jan 2014 09:52:11 +0100 Subject: [PATCH 18/24] #8725-R: refactoring of simplification API in FeatureIterators --- src/core/qgsfeatureiterator.cpp | 31 ++++++++++++------- src/core/qgsfeatureiterator.h | 7 +++-- src/core/qgsvectorlayerfeatureiterator.cpp | 13 ++++++-- src/providers/ogr/qgsogrfeatureiterator.cpp | 12 +++---- src/providers/ogr/qgsogrfeatureiterator.h | 4 +-- .../postgres/qgspostgresfeatureiterator.cpp | 10 +++--- .../postgres/qgspostgresfeatureiterator.h | 4 +-- 7 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/core/qgsfeatureiterator.cpp b/src/core/qgsfeatureiterator.cpp index 2d062e69fa40..370222d33b5a 100644 --- a/src/core/qgsfeatureiterator.cpp +++ b/src/core/qgsfeatureiterator.cpp @@ -55,16 +55,11 @@ bool QgsAbstractFeatureIterator::nextFeature( QgsFeature& f ) break; } - // simplify locally the geometry using the simplifier defined in constructor - if ( dataOk && mGeometrySimplifier ) + // simplify the geometry using the simplifier configured + if ( dataOk ) { QgsGeometry* geometry = f.geometry(); - - if ( geometry ) - { - QGis::GeometryType geometryType = geometry->type(); - if ( geometryType == QGis::Line || geometryType == QGis::Polygon ) mGeometrySimplifier->simplifyGeometry( geometry ); - } + if ( geometry ) simplify( f ); } return dataOk; } @@ -101,10 +96,8 @@ void QgsAbstractFeatureIterator::deref() delete this; } -bool QgsAbstractFeatureIterator::prepareLocalSimplification() +bool QgsAbstractFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simplifyMethod ) { - const QgsSimplifyMethod& simplifyMethod = mRequest.simplifyMethod(); - if ( mGeometrySimplifier ) { delete mGeometrySimplifier; @@ -136,6 +129,22 @@ bool QgsAbstractFeatureIterator::prepareLocalSimplification() return false; } +bool QgsAbstractFeatureIterator::simplify( QgsFeature& feature ) +{ + // simplify locally the geometry using the configured simplifier + if ( mGeometrySimplifier ) + { + QgsGeometry* geometry = feature.geometry(); + + if ( geometry ) + { + QGis::GeometryType geometryType = geometry->type(); + if ( geometryType == QGis::Line || geometryType == QGis::Polygon ) return mGeometrySimplifier->simplifyGeometry( geometry ); + } + } + return false; +} + /////// QgsFeatureIterator& QgsFeatureIterator::operator=( const QgsFeatureIterator & other ) diff --git a/src/core/qgsfeatureiterator.h b/src/core/qgsfeatureiterator.h index b1692977b3a6..c1dd576be6ec 100644 --- a/src/core/qgsfeatureiterator.h +++ b/src/core/qgsfeatureiterator.h @@ -87,12 +87,15 @@ class CORE_EXPORT QgsAbstractFeatureIterator void deref(); //!< remove reference, delete if refs == 0 friend class QgsFeatureIterator; - //! setup if required the local simplification of geometries to fetch, it uses the settings of current FeatureRequest - virtual bool prepareLocalSimplification(); + //! Setup the simplification of geometries to fetch using the specified simplify method + virtual bool prepareSimplification( const QgsSimplifyMethod& simplifyMethod ); private: //! optional object to locally simplify geometries fetched by this feature iterator QgsAbstractGeometrySimplifier* mGeometrySimplifier; + + //! simplify the specified geometry if it was configured + virtual bool simplify( QgsFeature& feature ); }; diff --git a/src/core/qgsvectorlayerfeatureiterator.cpp b/src/core/qgsvectorlayerfeatureiterator.cpp index f4a76512466a..e203c4fc49c7 100644 --- a/src/core/qgsvectorlayerfeatureiterator.cpp +++ b/src/core/qgsvectorlayerfeatureiterator.cpp @@ -68,6 +68,15 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la } else // no filter or filter by rect { + QgsSimplifyMethod simplifyMethod = request.simplifyMethod(); + + // if required, local simplification will be configured for all providers, then avoid simplify twice (this iterator and provider iterator) + if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && simplifyMethod.forceLocalOptimization() ) + { + simplifyMethod.setMethodType( QgsSimplifyMethod::NoSimplification ); + if ( L->editBuffer() ) mChangedFeaturesRequest.setSimplifyMethod( simplifyMethod ); else mProviderRequest.setSimplifyMethod( simplifyMethod ); + } + if ( L->editBuffer() ) { mChangedFeaturesIterator = L->dataProvider()->getFeatures( mChangedFeaturesRequest ); @@ -77,8 +86,8 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la mProviderIterator = L->dataProvider()->getFeatures( mProviderRequest ); } - // setup if required the local simplification of geometries to fetch - prepareLocalSimplification(); + // prepare if required the local simplification of geometries to fetch + prepareSimplification( request.simplifyMethod() ); rewindEditBuffer(); } diff --git a/src/providers/ogr/qgsogrfeatureiterator.cpp b/src/providers/ogr/qgsogrfeatureiterator.cpp index 835c21a20205..bfd4cbf505d6 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.cpp +++ b/src/providers/ogr/qgsogrfeatureiterator.cpp @@ -81,7 +81,7 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrProvider* p, const QgsFeatur } //setup if required the simplification of OGR-geometries fetched - prepareProviderSimplification(); + prepareSimplification( request.simplifyMethod() ); //start with first feature rewind(); @@ -105,9 +105,9 @@ void QgsOgrFeatureIterator::ensureRelevantFields() P->mRelevantFieldsForNextFeature = true; } -bool QgsOgrFeatureIterator::prepareProviderSimplification() +bool QgsOgrFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simplifyMethod ) { - const QgsSimplifyMethod& simplifyMethod = mRequest.simplifyMethod(); + bool providerSimplification = false; if ( mGeometrySimplifier ) { @@ -124,20 +124,20 @@ bool QgsOgrFeatureIterator::prepareProviderSimplification() { int simplifyFlags = QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope; mGeometrySimplifier = new QgsOgrMapToPixelSimplifier( simplifyFlags, simplifyMethod.tolerance() ); - return true; + providerSimplification = true; } else if ( methodType == QgsSimplifyMethod::PreserveTopology ) { mGeometrySimplifier = new QgsOgrTopologyPreservingSimplifier( simplifyMethod.tolerance() ); - return true; + providerSimplification = true; } else { QgsDebugMsg( QString( "Simplification method type (%1) is not recognised by OgrFeatureIterator class" ).arg( methodType ) ); } } - return false; + return QgsAbstractFeatureIterator::prepareSimplification( simplifyMethod ) || providerSimplification; } bool QgsOgrFeatureIterator::fetchFeature( QgsFeature& feature ) diff --git a/src/providers/ogr/qgsogrfeatureiterator.h b/src/providers/ogr/qgsogrfeatureiterator.h index 43ee2cc233b9..3b03be33750b 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.h +++ b/src/providers/ogr/qgsogrfeatureiterator.h @@ -39,8 +39,8 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator //! fetch next feature, return true on success virtual bool fetchFeature( QgsFeature& feature ); - //! setup if required the simplification of OGR-geometries fetched, it uses the settings of current FeatureRequest - virtual bool prepareProviderSimplification(); + //! Setup the simplification of geometries to fetch using the specified simplify method + virtual bool prepareSimplification( const QgsSimplifyMethod& simplifyMethod ); QgsOgrProvider* P; diff --git a/src/providers/postgres/qgspostgresfeatureiterator.cpp b/src/providers/postgres/qgspostgresfeatureiterator.cpp index ca7093fcbbe8..6f1e9edb143d 100644 --- a/src/providers/postgres/qgspostgresfeatureiterator.cpp +++ b/src/providers/postgres/qgspostgresfeatureiterator.cpp @@ -81,7 +81,7 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresProvider* p, } //setup if required the simplification of geometries to fetch - prepareProviderSimplification(); + prepareSimplification( request.simplifyMethod() ); mFetched = 0; } @@ -173,9 +173,9 @@ bool QgsPostgresFeatureIterator::fetchFeature( QgsFeature& feature ) return true; } -bool QgsPostgresFeatureIterator::prepareProviderSimplification() +bool QgsPostgresFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simplifyMethod ) { - const QgsSimplifyMethod& simplifyMethod = mRequest.simplifyMethod(); + bool providerSimplification = false; // validate settings of simplification of geometries to fetch if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !simplifyMethod.forceLocalOptimization() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) @@ -184,14 +184,14 @@ bool QgsPostgresFeatureIterator::prepareProviderSimplification() if ( methodType == QgsSimplifyMethod::OptimizeForRendering || methodType == QgsSimplifyMethod::PreserveTopology ) { - return true; + providerSimplification = true; } else { QgsDebugMsg( QString( "Simplification method type (%1) is not recognised by PostgresFeatureIterator" ).arg( methodType ) ); } } - return false; + return QgsAbstractFeatureIterator::prepareSimplification( simplifyMethod ) || providerSimplification; } bool QgsPostgresFeatureIterator::rewind() diff --git a/src/providers/postgres/qgspostgresfeatureiterator.h b/src/providers/postgres/qgspostgresfeatureiterator.h index b4ba18716d51..f00c24bec2e5 100644 --- a/src/providers/postgres/qgspostgresfeatureiterator.h +++ b/src/providers/postgres/qgspostgresfeatureiterator.h @@ -40,8 +40,8 @@ class QgsPostgresFeatureIterator : public QgsAbstractFeatureIterator //! fetch next feature, return true on success virtual bool fetchFeature( QgsFeature& feature ); - //! setup if required the simplification of geometries to fetch, it uses the settings of current FeatureRequest - virtual bool prepareProviderSimplification(); + //! Setup the simplification of geometries to fetch using the specified simplify method + virtual bool prepareSimplification( const QgsSimplifyMethod& simplifyMethod ); QgsPostgresProvider* P; From 972a7587dc62c383e38a08d44ca567d03f686e4b Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Sat, 11 Jan 2014 11:12:51 +0100 Subject: [PATCH 19/24] #8725-R: simplify edited geometries in QgsVectorLayerFeatureIterator --- python/core/core.sip | 2 + python/core/qgsgeometrysimplifier.sip | 23 +++++++++ python/core/qgssimplifymethod.sip | 39 ++++++++++++++++ src/core/qgsfeatureiterator.cpp | 23 ++------- src/core/qgssimplifymethod.cpp | 25 ++++++++++ src/core/qgssimplifymethod.h | 5 ++ src/core/qgsvectorlayerfeatureiterator.cpp | 52 +++++++++++++++++++-- src/core/qgsvectorlayerfeatureiterator.h | 7 +++ src/providers/ogr/qgsogrfeatureiterator.cpp | 2 +- 9 files changed, 153 insertions(+), 25 deletions(-) create mode 100644 python/core/qgsgeometrysimplifier.sip create mode 100644 python/core/qgssimplifymethod.sip diff --git a/python/core/core.sip b/python/core/core.sip index aca5927372c7..0e86c382bc7f 100644 --- a/python/core/core.sip +++ b/python/core/core.sip @@ -37,6 +37,7 @@ %Include qgsfield.sip %Include qgsgeometry.sip %Include qgsgeometryvalidator.sip +%Include qgsgeometrysimplifier.sip %Include qgsgml.sip %Include qgsgmlschema.sip %Include qgshttptransaction.sip @@ -75,6 +76,7 @@ %Include qgsrunprocess.sip %Include qgsscalecalculator.sip %Include qgsscaleutils.sip +%Include qgssimplifymethod.sip %Include qgssnapper.sip %Include qgsspatialindex.sip %Include qgstolerance.sip diff --git a/python/core/qgsgeometrysimplifier.sip b/python/core/qgsgeometrysimplifier.sip new file mode 100644 index 000000000000..aac53df86b97 --- /dev/null +++ b/python/core/qgsgeometrysimplifier.sip @@ -0,0 +1,23 @@ + +/** Abstract base class for simplify geometries using a specific algorithm */ +class QgsAbstractGeometrySimplifier +{ +%TypeHeaderCode +#include "qgsgeometrysimplifier.h" +%End + + public: + virtual ~QgsAbstractGeometrySimplifier(); + + /** Returns a simplified version the specified geometry */ + virtual QgsGeometry* simplify( QgsGeometry* geometry ) const = 0; + /** Simplifies the specified geometry */ + virtual bool simplifyGeometry( QgsGeometry* geometry ) const = 0; + + // MapToPixel simplification helper methods + public: + /** Returns whether the device-envelope can be replaced by its BBOX when is applied the specified tolerance */ + static bool canbeGeneralizedByDeviceBoundingBox( const QgsRectangle& envelope, float mapToPixelTol = 1.0f ); + /** Returns whether the device-geometry can be replaced by its BBOX when is applied the specified tolerance */ + static bool canbeGeneralizedByDeviceBoundingBox( const QVector& points, float mapToPixelTol = 1.0f ); +}; diff --git a/python/core/qgssimplifymethod.sip b/python/core/qgssimplifymethod.sip new file mode 100644 index 000000000000..55db7bb01daf --- /dev/null +++ b/python/core/qgssimplifymethod.sip @@ -0,0 +1,39 @@ + +/** This class contains information about how to simplify geometries fetched from a QgsFeatureIterator */ +class QgsSimplifyMethod +{ +%TypeHeaderCode +#include "qgssimplifymethod.h" +%End + + public: + enum MethodType + { + NoSimplification, //!< No simplification is applied + OptimizeForRendering, //!< Simplify using the map2pixel data to optimize the rendering of geometries + PreserveTopology //!< Simplify using the Douglas-Peucker algorithm ensuring that the result is a valid geometry + }; + + //! construct a default method + QgsSimplifyMethod(); + //! copy constructor + QgsSimplifyMethod( const QgsSimplifyMethod& rh ); + + /** Sets the simplification type */ + void setMethodType( MethodType methodType ); + /** Gets the simplification type */ + MethodType methodType() const; + + /** Sets the tolerance of simplification. Represents the maximum distance between two coordinates which can be considered equal */ + void setTolerance( double tolerance ); + /** Gets the tolerance of simplification */ + double tolerance() const; + + /** Sets whether the simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries */ + void setForceLocalOptimization( bool localOptimization ); + /** Gets whether the simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries */ + bool forceLocalOptimization() const; + + /** Creates a geometry simplifier according to specified method */ + static QgsAbstractGeometrySimplifier* createGeometrySimplifier( const QgsSimplifyMethod& simplifyMethod ); +}; diff --git a/src/core/qgsfeatureiterator.cpp b/src/core/qgsfeatureiterator.cpp index 370222d33b5a..1dfc555b44aa 100644 --- a/src/core/qgsfeatureiterator.cpp +++ b/src/core/qgsfeatureiterator.cpp @@ -16,7 +16,6 @@ #include "qgslogger.h" #include "qgsgeometrysimplifier.h" -#include "qgsmaptopixelgeometrysimplifier.h" #include "qgssimplifymethod.h" QgsAbstractFeatureIterator::QgsAbstractFeatureIterator( const QgsFeatureRequest& request ) @@ -104,27 +103,11 @@ bool QgsAbstractFeatureIterator::prepareSimplification( const QgsSimplifyMethod& mGeometrySimplifier = NULL; } - // setup the local simplification of geometries to fetch, it uses the settings of current FeatureRequest + // setup the local simplification of geometries to fetch if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && simplifyMethod.forceLocalOptimization() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { - QgsSimplifyMethod::MethodType methodType = simplifyMethod.methodType(); - - if ( methodType == QgsSimplifyMethod::OptimizeForRendering ) - { - int simplifyFlags = QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope; - mGeometrySimplifier = new QgsMapToPixelSimplifier( simplifyFlags, simplifyMethod.tolerance() ); - return true; - } - else - if ( methodType == QgsSimplifyMethod::PreserveTopology ) - { - mGeometrySimplifier = new QgsTopologyPreservingSimplifier( simplifyMethod.tolerance() ); - return true; - } - else - { - QgsDebugMsg( QString( "Simplification method type (%1) is not recognised" ).arg( methodType ) ); - } + mGeometrySimplifier = QgsSimplifyMethod::createGeometrySimplifier( simplifyMethod ); + return mGeometrySimplifier != NULL; } return false; } diff --git a/src/core/qgssimplifymethod.cpp b/src/core/qgssimplifymethod.cpp index a2efeea73442..b3a6e89b74f5 100644 --- a/src/core/qgssimplifymethod.cpp +++ b/src/core/qgssimplifymethod.cpp @@ -14,6 +14,9 @@ ***************************************************************************/ #include "qgssimplifymethod.h" +#include "qgslogger.h" +#include "qgsgeometrysimplifier.h" +#include "qgsmaptopixelgeometrysimplifier.h" QgsSimplifyMethod::QgsSimplifyMethod() : mMethodType( QgsSimplifyMethod::NoSimplification ) @@ -50,3 +53,25 @@ void QgsSimplifyMethod::setForceLocalOptimization( bool localOptimization ) { mForceLocalOptimization = localOptimization; } + +QgsAbstractGeometrySimplifier* QgsSimplifyMethod::createGeometrySimplifier( const QgsSimplifyMethod& simplifyMethod ) +{ + QgsSimplifyMethod::MethodType methodType = simplifyMethod.methodType(); + + // returns a geometry simplifier according to specified method + if ( methodType == QgsSimplifyMethod::OptimizeForRendering ) + { + int simplifyFlags = QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope; + return new QgsMapToPixelSimplifier( simplifyFlags, simplifyMethod.tolerance() ); + } + else + if ( methodType == QgsSimplifyMethod::PreserveTopology ) + { + return new QgsTopologyPreservingSimplifier( simplifyMethod.tolerance() ); + } + else + { + QgsDebugMsg( QString( "Simplification method type (%1) is not recognised" ).arg( methodType ) ); + return NULL; + } +} diff --git a/src/core/qgssimplifymethod.h b/src/core/qgssimplifymethod.h index 276361445db2..2143ffbaf191 100644 --- a/src/core/qgssimplifymethod.h +++ b/src/core/qgssimplifymethod.h @@ -16,6 +16,8 @@ #ifndef QGSSIMPLIFYMETHOD_H #define QGSSIMPLIFYMETHOD_H +class QgsAbstractGeometrySimplifier; + /** * This class contains information about how to simplify geometries fetched from a QgsFeatureIterator */ @@ -51,6 +53,9 @@ class CORE_EXPORT QgsSimplifyMethod //! Gets whether the simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries inline bool forceLocalOptimization() const { return mForceLocalOptimization; } + //! Creates a geometry simplifier according to specified method + static QgsAbstractGeometrySimplifier* createGeometrySimplifier( const QgsSimplifyMethod& simplifyMethod ); + protected: //! Simplification method MethodType mMethodType; diff --git a/src/core/qgsvectorlayerfeatureiterator.cpp b/src/core/qgsvectorlayerfeatureiterator.cpp index e203c4fc49c7..119b32d6f8b3 100644 --- a/src/core/qgsvectorlayerfeatureiterator.cpp +++ b/src/core/qgsvectorlayerfeatureiterator.cpp @@ -19,9 +19,11 @@ #include "qgsvectorlayer.h" #include "qgsvectorlayereditbuffer.h" #include "qgsvectorlayerjoinbuffer.h" +#include "qgsgeometrysimplifier.h" +#include "qgssimplifymethod.h" QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* layer, const QgsFeatureRequest& request ) - : QgsAbstractFeatureIterator( request ), L( layer ) + : QgsAbstractFeatureIterator( request ), L( layer ), mEditGeometrySimplifier( NULL ) { QgsVectorLayerJoinBuffer* joinBuffer = L->mJoinBuffer; @@ -86,9 +88,6 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la mProviderIterator = L->dataProvider()->getFeatures( mProviderRequest ); } - // prepare if required the local simplification of geometries to fetch - prepareSimplification( request.simplifyMethod() ); - rewindEditBuffer(); } @@ -96,11 +95,20 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la { mRequest.filterExpression()->prepare( L->pendingFields() ); } + + // prepare if required the local simplification of geometries to fetch + prepareSimplification( request.simplifyMethod() ); } QgsVectorLayerFeatureIterator::~QgsVectorLayerFeatureIterator() { + if ( mEditGeometrySimplifier ) + { + delete mEditGeometrySimplifier; + mEditGeometrySimplifier = NULL; + } + close(); } @@ -242,8 +250,18 @@ void QgsVectorLayerFeatureIterator::useAddedFeature( const QgsFeature& src, QgsF f.setFields( &L->mUpdatedFields ); if ( src.geometry() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) + { f.setGeometry( *src.geometry() ); + // simplify the edited geometry using its simplifier configured + if ( mEditGeometrySimplifier ) + { + QgsGeometry* geometry = f.geometry(); + QGis::GeometryType geometryType = geometry->type(); + if ( geometryType == QGis::Line || geometryType == QGis::Polygon ) mEditGeometrySimplifier->simplifyGeometry( geometry ); + } + } + // TODO[MD]: if subset set just some attributes f.setAttributes( src.attributes() ); @@ -313,8 +331,18 @@ void QgsVectorLayerFeatureIterator::useChangedAttributeFeature( QgsFeatureId fid f.setFields( &L->mUpdatedFields ); if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) + { f.setGeometry( geom ); + // simplify the edited geometry using its simplifier configured + if ( mEditGeometrySimplifier ) + { + QgsGeometry* geometry = f.geometry(); + QGis::GeometryType geometryType = geometry->type(); + if ( geometryType == QGis::Line || geometryType == QGis::Polygon ) mEditGeometrySimplifier->simplifyGeometry( geometry ); + } + } + bool subsetAttrs = ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ); if ( !subsetAttrs || ( subsetAttrs && mRequest.subsetOfAttributes().count() > 0 ) ) { @@ -436,6 +464,22 @@ void QgsVectorLayerFeatureIterator::addJoinedAttributes( QgsFeature &f ) } } +bool QgsVectorLayerFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simplifyMethod ) +{ + if ( mEditGeometrySimplifier ) + { + delete mEditGeometrySimplifier; + mEditGeometrySimplifier = NULL; + } + + // setup the simplification of edited geometries to fetch + if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) + { + mEditGeometrySimplifier = QgsSimplifyMethod::createGeometrySimplifier( simplifyMethod ); + } + + return QgsAbstractFeatureIterator::prepareSimplification( simplifyMethod ); +} void QgsVectorLayerFeatureIterator::FetchJoinInfo::addJoinedAttributesCached( QgsFeature& f, const QVariant& joinValue ) const diff --git a/src/core/qgsvectorlayerfeatureiterator.h b/src/core/qgsvectorlayerfeatureiterator.h index 077dc6f31659..b09720aab701 100644 --- a/src/core/qgsvectorlayerfeatureiterator.h +++ b/src/core/qgsvectorlayerfeatureiterator.h @@ -46,6 +46,9 @@ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureItera //! while for others filtering is left to the provider implementation. inline virtual bool nextFeatureFilterExpression( QgsFeature &f ) { return fetchFeature( f ); } + //! Setup the simplification of geometries to fetch using the specified simplify method + virtual bool prepareSimplification( const QgsSimplifyMethod& simplifyMethod ); + QgsVectorLayer* L; QgsFeatureRequest mProviderRequest; @@ -114,6 +117,10 @@ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureItera /** Informations about joins used in the current select() statement. Allows faster mapping of attribute ids compared to mVectorJoins */ QMap mFetchJoinInfo; + + private: + //! optional object to locally simplify edited (changed or added) geometries fetched by this feature iterator + QgsAbstractGeometrySimplifier* mEditGeometrySimplifier; }; #endif // QGSVECTORLAYERFEATUREITERATOR_H diff --git a/src/providers/ogr/qgsogrfeatureiterator.cpp b/src/providers/ogr/qgsogrfeatureiterator.cpp index bfd4cbf505d6..8b57b79d78dd 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.cpp +++ b/src/providers/ogr/qgsogrfeatureiterator.cpp @@ -115,7 +115,7 @@ bool QgsOgrFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simp mGeometrySimplifier = NULL; } - // setup if required the simplification of OGR-geometries fetched, it uses the settings of current FeatureRequest + // setup if required the simplification of OGR-geometries fetched if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !simplifyMethod.forceLocalOptimization() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { QgsSimplifyMethod::MethodType methodType = simplifyMethod.methodType(); From e1f60405cea1db07f17f77694456814cd1e02b4b Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Mon, 13 Jan 2014 22:27:46 +0100 Subject: [PATCH 20/24] #8725-R: no check 0-pointers to delete --- src/core/qgsfeatureiterator.cpp | 14 ++++---------- src/core/qgsvectorlayerfeatureiterator.cpp | 14 ++++---------- src/providers/ogr/qgsogrfeatureiterator.cpp | 15 +++++---------- 3 files changed, 13 insertions(+), 30 deletions(-) diff --git a/src/core/qgsfeatureiterator.cpp b/src/core/qgsfeatureiterator.cpp index 1dfc555b44aa..8430f5cf8373 100644 --- a/src/core/qgsfeatureiterator.cpp +++ b/src/core/qgsfeatureiterator.cpp @@ -28,11 +28,8 @@ QgsAbstractFeatureIterator::QgsAbstractFeatureIterator( const QgsFeatureRequest& QgsAbstractFeatureIterator::~QgsAbstractFeatureIterator() { - if ( mGeometrySimplifier ) - { - delete mGeometrySimplifier; - mGeometrySimplifier = NULL; - } + delete mGeometrySimplifier; + mGeometrySimplifier = NULL; } bool QgsAbstractFeatureIterator::nextFeature( QgsFeature& f ) @@ -97,11 +94,8 @@ void QgsAbstractFeatureIterator::deref() bool QgsAbstractFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simplifyMethod ) { - if ( mGeometrySimplifier ) - { - delete mGeometrySimplifier; - mGeometrySimplifier = NULL; - } + delete mGeometrySimplifier; + mGeometrySimplifier = NULL; // setup the local simplification of geometries to fetch if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && simplifyMethod.forceLocalOptimization() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) diff --git a/src/core/qgsvectorlayerfeatureiterator.cpp b/src/core/qgsvectorlayerfeatureiterator.cpp index 119b32d6f8b3..564cb371747b 100644 --- a/src/core/qgsvectorlayerfeatureiterator.cpp +++ b/src/core/qgsvectorlayerfeatureiterator.cpp @@ -103,11 +103,8 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la QgsVectorLayerFeatureIterator::~QgsVectorLayerFeatureIterator() { - if ( mEditGeometrySimplifier ) - { - delete mEditGeometrySimplifier; - mEditGeometrySimplifier = NULL; - } + delete mEditGeometrySimplifier; + mEditGeometrySimplifier = NULL; close(); } @@ -466,11 +463,8 @@ void QgsVectorLayerFeatureIterator::addJoinedAttributes( QgsFeature &f ) bool QgsVectorLayerFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simplifyMethod ) { - if ( mEditGeometrySimplifier ) - { - delete mEditGeometrySimplifier; - mEditGeometrySimplifier = NULL; - } + delete mEditGeometrySimplifier; + mEditGeometrySimplifier = NULL; // setup the simplification of edited geometries to fetch if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) diff --git a/src/providers/ogr/qgsogrfeatureiterator.cpp b/src/providers/ogr/qgsogrfeatureiterator.cpp index 8b57b79d78dd..9552e98908c8 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.cpp +++ b/src/providers/ogr/qgsogrfeatureiterator.cpp @@ -89,11 +89,9 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrProvider* p, const QgsFeatur QgsOgrFeatureIterator::~QgsOgrFeatureIterator() { - if ( mGeometrySimplifier ) - { - delete mGeometrySimplifier; - mGeometrySimplifier = NULL; - } + delete mGeometrySimplifier; + mGeometrySimplifier = NULL; + close(); } @@ -109,11 +107,8 @@ bool QgsOgrFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simp { bool providerSimplification = false; - if ( mGeometrySimplifier ) - { - delete mGeometrySimplifier; - mGeometrySimplifier = NULL; - } + delete mGeometrySimplifier; + mGeometrySimplifier = NULL; // setup if required the simplification of OGR-geometries fetched if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !simplifyMethod.forceLocalOptimization() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) From 11644386c84be8ea781155c9ef3b1843c5022322 Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Mon, 13 Jan 2014 23:03:54 +0100 Subject: [PATCH 21/24] #8725-R: no check geometry pointer twice --- src/core/qgsfeatureiterator.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/core/qgsfeatureiterator.cpp b/src/core/qgsfeatureiterator.cpp index 8430f5cf8373..e7bc82b6785b 100644 --- a/src/core/qgsfeatureiterator.cpp +++ b/src/core/qgsfeatureiterator.cpp @@ -113,11 +113,8 @@ bool QgsAbstractFeatureIterator::simplify( QgsFeature& feature ) { QgsGeometry* geometry = feature.geometry(); - if ( geometry ) - { - QGis::GeometryType geometryType = geometry->type(); - if ( geometryType == QGis::Line || geometryType == QGis::Polygon ) return mGeometrySimplifier->simplifyGeometry( geometry ); - } + QGis::GeometryType geometryType = geometry->type(); + if ( geometryType == QGis::Line || geometryType == QGis::Polygon ) return mGeometrySimplifier->simplifyGeometry( geometry ); } return false; } From 89c1feaa4f43a2fd4c854aeb2f37fc9a7e5c0ea8 Mon Sep 17 00:00:00 2001 From: Alvaro Huarte Date: Tue, 14 Jan 2014 17:19:55 +0100 Subject: [PATCH 22/24] #8275-R: simplification on a per-iterator basis --- src/core/qgsfeatureiterator.cpp | 22 +++++++++-- src/core/qgsfeatureiterator.h | 5 +++ src/core/qgsvectorlayer.cpp | 7 ---- src/core/qgsvectorlayerfeatureiterator.cpp | 39 ++++++++++++------- src/core/qgsvectorlayerfeatureiterator.h | 3 ++ src/providers/ogr/qgsogrfeatureiterator.cpp | 20 +++++----- src/providers/ogr/qgsogrfeatureiterator.h | 3 ++ .../postgres/qgspostgresfeatureiterator.cpp | 18 ++++----- .../postgres/qgspostgresfeatureiterator.h | 3 ++ 9 files changed, 75 insertions(+), 45 deletions(-) diff --git a/src/core/qgsfeatureiterator.cpp b/src/core/qgsfeatureiterator.cpp index e7bc82b6785b..71806e0c8253 100644 --- a/src/core/qgsfeatureiterator.cpp +++ b/src/core/qgsfeatureiterator.cpp @@ -23,6 +23,7 @@ QgsAbstractFeatureIterator::QgsAbstractFeatureIterator( const QgsFeatureRequest& , mClosed( false ) , refs( 0 ) , mGeometrySimplifier( NULL ) + , mLocalSimplification( false ) { } @@ -52,7 +53,7 @@ bool QgsAbstractFeatureIterator::nextFeature( QgsFeature& f ) } // simplify the geometry using the simplifier configured - if ( dataOk ) + if ( dataOk && mLocalSimplification ) { QgsGeometry* geometry = f.geometry(); if ( geometry ) simplify( f ); @@ -82,6 +83,11 @@ bool QgsAbstractFeatureIterator::nextFeatureFilterFids( QgsFeature& f ) void QgsAbstractFeatureIterator::ref() { + // prepare if required the simplification of geometries to fetch + if ( refs == 0 ) + { + prepareSimplification( mRequest.simplifyMethod() ); + } refs++; } @@ -94,18 +100,26 @@ void QgsAbstractFeatureIterator::deref() bool QgsAbstractFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simplifyMethod ) { + mLocalSimplification = false; + delete mGeometrySimplifier; mGeometrySimplifier = NULL; - // setup the local simplification of geometries to fetch - if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && simplifyMethod.forceLocalOptimization() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) + // setup the simplification of geometries to fetch + if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && ( simplifyMethod.forceLocalOptimization() || !providerCanSimplify( simplifyMethod.methodType() ) ) ) { mGeometrySimplifier = QgsSimplifyMethod::createGeometrySimplifier( simplifyMethod ); - return mGeometrySimplifier != NULL; + mLocalSimplification = mGeometrySimplifier != NULL; + return mLocalSimplification; } return false; } +bool QgsAbstractFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const +{ + return false; +} + bool QgsAbstractFeatureIterator::simplify( QgsFeature& feature ) { // simplify locally the geometry using the configured simplifier diff --git a/src/core/qgsfeatureiterator.h b/src/core/qgsfeatureiterator.h index c1dd576be6ec..86926b9bfcd0 100644 --- a/src/core/qgsfeatureiterator.h +++ b/src/core/qgsfeatureiterator.h @@ -93,6 +93,11 @@ class CORE_EXPORT QgsAbstractFeatureIterator private: //! optional object to locally simplify geometries fetched by this feature iterator QgsAbstractGeometrySimplifier* mGeometrySimplifier; + //! this iterator runs local simplification + bool mLocalSimplification; + + //! returns whether the iterator can simplify on provider side the geometries to fetch using the specified method type + virtual bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const; //! simplify the specified geometry if it was configured virtual bool simplify( QgsFeature& feature ); diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index 25792e55fff1..f3f8b9fb8c7c 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -737,13 +737,6 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext ) simplifyMethod.setTolerance( map2pixelTol ); simplifyMethod.setForceLocalOptimization( mSimplifyMethod.forceLocalOptimization() ); - // fix simplification non supported on server side - if ( !simplifyMethod.forceLocalOptimization() && !( mDataProvider->capabilities() & QgsVectorDataProvider::SimplifyGeometries ) ) - { - QgsDebugMsg( "Data provider does not support geometry simplification on provider side" ); - simplifyMethod.setForceLocalOptimization( true ); - } - featureRequest.setSimplifyMethod( simplifyMethod ); } diff --git a/src/core/qgsvectorlayerfeatureiterator.cpp b/src/core/qgsvectorlayerfeatureiterator.cpp index 564cb371747b..8f026bb1c407 100644 --- a/src/core/qgsvectorlayerfeatureiterator.cpp +++ b/src/core/qgsvectorlayerfeatureiterator.cpp @@ -70,15 +70,6 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la } else // no filter or filter by rect { - QgsSimplifyMethod simplifyMethod = request.simplifyMethod(); - - // if required, local simplification will be configured for all providers, then avoid simplify twice (this iterator and provider iterator) - if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && simplifyMethod.forceLocalOptimization() ) - { - simplifyMethod.setMethodType( QgsSimplifyMethod::NoSimplification ); - if ( L->editBuffer() ) mChangedFeaturesRequest.setSimplifyMethod( simplifyMethod ); else mProviderRequest.setSimplifyMethod( simplifyMethod ); - } - if ( L->editBuffer() ) { mChangedFeaturesIterator = L->dataProvider()->getFeatures( mChangedFeaturesRequest ); @@ -95,9 +86,6 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* la { mRequest.filterExpression()->prepare( L->pendingFields() ); } - - // prepare if required the local simplification of geometries to fetch - prepareSimplification( request.simplifyMethod() ); } @@ -466,13 +454,34 @@ bool QgsVectorLayerFeatureIterator::prepareSimplification( const QgsSimplifyMeth delete mEditGeometrySimplifier; mEditGeometrySimplifier = NULL; - // setup the simplification of edited geometries to fetch - if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) + // setup simplification for edited geometries to fetch + if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification ) { mEditGeometrySimplifier = QgsSimplifyMethod::createGeometrySimplifier( simplifyMethod ); + return mEditGeometrySimplifier != NULL; } + return false; +} + +bool QgsVectorLayerFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const +{ + QgsVectorDataProvider* provider = L->dataProvider(); - return QgsAbstractFeatureIterator::prepareSimplification( simplifyMethod ); + if ( provider && methodType != QgsSimplifyMethod::NoSimplification ) + { + int capabilities = provider->capabilities(); + + if ( methodType == QgsSimplifyMethod::OptimizeForRendering ) + { + return ( capabilities & QgsVectorDataProvider::SimplifyGeometries ); + } + else + if ( methodType == QgsSimplifyMethod::PreserveTopology ) + { + return ( capabilities & QgsVectorDataProvider::SimplifyGeometriesWithTopologicalValidation ); + } + } + return false; } diff --git a/src/core/qgsvectorlayerfeatureiterator.h b/src/core/qgsvectorlayerfeatureiterator.h index b09720aab701..d00bc8e05e09 100644 --- a/src/core/qgsvectorlayerfeatureiterator.h +++ b/src/core/qgsvectorlayerfeatureiterator.h @@ -121,6 +121,9 @@ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureItera private: //! optional object to locally simplify edited (changed or added) geometries fetched by this feature iterator QgsAbstractGeometrySimplifier* mEditGeometrySimplifier; + + //! returns whether the iterator can simplify on provider side the geometries to fetch using the specified method type + virtual bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const; }; #endif // QGSVECTORLAYERFEATUREITERATOR_H diff --git a/src/providers/ogr/qgsogrfeatureiterator.cpp b/src/providers/ogr/qgsogrfeatureiterator.cpp index 9552e98908c8..dba1f78967fa 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.cpp +++ b/src/providers/ogr/qgsogrfeatureiterator.cpp @@ -80,9 +80,6 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrProvider* p, const QgsFeatur OGR_L_SetSpatialFilter( ogrLayer, 0 ); } - //setup if required the simplification of OGR-geometries fetched - prepareSimplification( request.simplifyMethod() ); - //start with first feature rewind(); } @@ -105,13 +102,11 @@ void QgsOgrFeatureIterator::ensureRelevantFields() bool QgsOgrFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simplifyMethod ) { - bool providerSimplification = false; - delete mGeometrySimplifier; mGeometrySimplifier = NULL; - // setup if required the simplification of OGR-geometries fetched - if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !simplifyMethod.forceLocalOptimization() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) + // setup simplification of OGR-geometries fetched + if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !simplifyMethod.forceLocalOptimization() ) { QgsSimplifyMethod::MethodType methodType = simplifyMethod.methodType(); @@ -119,20 +114,25 @@ bool QgsOgrFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simp { int simplifyFlags = QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope; mGeometrySimplifier = new QgsOgrMapToPixelSimplifier( simplifyFlags, simplifyMethod.tolerance() ); - providerSimplification = true; + return true; } else if ( methodType == QgsSimplifyMethod::PreserveTopology ) { mGeometrySimplifier = new QgsOgrTopologyPreservingSimplifier( simplifyMethod.tolerance() ); - providerSimplification = true; + return true; } else { QgsDebugMsg( QString( "Simplification method type (%1) is not recognised by OgrFeatureIterator class" ).arg( methodType ) ); } } - return QgsAbstractFeatureIterator::prepareSimplification( simplifyMethod ) || providerSimplification; + return QgsAbstractFeatureIterator::prepareSimplification( simplifyMethod ); +} + +bool QgsOgrFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const +{ + return methodType == QgsSimplifyMethod::OptimizeForRendering || methodType == QgsSimplifyMethod::PreserveTopology; } bool QgsOgrFeatureIterator::fetchFeature( QgsFeature& feature ) diff --git a/src/providers/ogr/qgsogrfeatureiterator.h b/src/providers/ogr/qgsogrfeatureiterator.h index 3b03be33750b..156b0355538d 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.h +++ b/src/providers/ogr/qgsogrfeatureiterator.h @@ -64,6 +64,9 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator private: //! optional object to simplify OGR-geometries fecthed by this feature iterator QgsOgrAbstractGeometrySimplifier* mGeometrySimplifier; + + //! returns whether the iterator can simplify on provider side the geometries to fetch using the specified method type + virtual bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const; }; #endif // QGSOGRFEATUREITERATOR_H diff --git a/src/providers/postgres/qgspostgresfeatureiterator.cpp b/src/providers/postgres/qgspostgresfeatureiterator.cpp index 6f1e9edb143d..da8dac128c6b 100644 --- a/src/providers/postgres/qgspostgresfeatureiterator.cpp +++ b/src/providers/postgres/qgspostgresfeatureiterator.cpp @@ -80,9 +80,6 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresProvider* p, return; } - //setup if required the simplification of geometries to fetch - prepareSimplification( request.simplifyMethod() ); - mFetched = 0; } @@ -175,23 +172,26 @@ bool QgsPostgresFeatureIterator::fetchFeature( QgsFeature& feature ) bool QgsPostgresFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simplifyMethod ) { - bool providerSimplification = false; - - // validate settings of simplification of geometries to fetch - if ( simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !simplifyMethod.forceLocalOptimization() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) + // setup simplification of geometries to fetch + if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !simplifyMethod.forceLocalOptimization() ) { QgsSimplifyMethod::MethodType methodType = simplifyMethod.methodType(); if ( methodType == QgsSimplifyMethod::OptimizeForRendering || methodType == QgsSimplifyMethod::PreserveTopology ) { - providerSimplification = true; + return true; } else { QgsDebugMsg( QString( "Simplification method type (%1) is not recognised by PostgresFeatureIterator" ).arg( methodType ) ); } } - return QgsAbstractFeatureIterator::prepareSimplification( simplifyMethod ) || providerSimplification; + return QgsAbstractFeatureIterator::prepareSimplification( simplifyMethod ); +} + +bool QgsPostgresFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const +{ + return methodType == QgsSimplifyMethod::OptimizeForRendering || methodType == QgsSimplifyMethod::PreserveTopology; } bool QgsPostgresFeatureIterator::rewind() diff --git a/src/providers/postgres/qgspostgresfeatureiterator.h b/src/providers/postgres/qgspostgresfeatureiterator.h index f00c24bec2e5..fa4e9da53aba 100644 --- a/src/providers/postgres/qgspostgresfeatureiterator.h +++ b/src/providers/postgres/qgspostgresfeatureiterator.h @@ -69,6 +69,9 @@ class QgsPostgresFeatureIterator : public QgsAbstractFeatureIterator static const int sFeatureQueueSize; + private: + //! returns whether the iterator can simplify on provider side the geometries to fetch using the specified method type + virtual bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const; }; #endif // QGSPOSTGRESFEATUREITERATOR_H From 39225b4515aaf4f0eddb0a37cb01738393b173d2 Mon Sep 17 00:00:00 2001 From: ahuarte47 Date: Wed, 15 Jan 2014 00:33:14 +0100 Subject: [PATCH 23/24] #8725-R: minor changes and UI update + add comment about 'prepareSimplification' in constructor + fix comment in 'providerCanSimplify' + improve UI messages --- src/app/qgsoptions.cpp | 15 +- src/app/qgsoptions.h | 2 - src/app/qgsvectorlayerproperties.cpp | 14 +- src/app/qgsvectorlayerproperties.h | 1 - src/core/qgsfeatureiterator.cpp | 6 +- src/core/qgsfeatureiterator.h | 2 +- src/core/qgsvectorlayerfeatureiterator.h | 2 +- src/providers/ogr/qgsogrfeatureiterator.h | 2 +- .../postgres/qgspostgresfeatureiterator.h | 2 +- src/ui/qgsoptionsbase.ui | 242 ++++------------- src/ui/qgsvectorlayerpropertiesbase.ui | 247 ++++-------------- 11 files changed, 129 insertions(+), 406 deletions(-) diff --git a/src/app/qgsoptions.cpp b/src/app/qgsoptions.cpp index aceddc975a98..54dcf479942e 100644 --- a/src/app/qgsoptions.cpp +++ b/src/app/qgsoptions.cpp @@ -563,10 +563,8 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) : // Default simplify drawing configuration mSimplifyDrawingGroupBox->setChecked( settings.value( "/qgis/simplifyDrawingHints", ( int )QgsVectorLayer::GeometrySimplification ).toInt() != QgsVectorLayer::NoSimplification ); - mSimplifyDrawingSlider->setValue(( int )( 5.0f * ( settings.value( "/qgis/simplifyDrawingTol", QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ).toFloat() - 1 ) ) ); + mSimplifyDrawingSpinBox->setValue( settings.value( "/qgis/simplifyDrawingTol", QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ).toFloat() ); mSimplifyDrawingAtProvider->setChecked( !settings.value( "/qgis/simplifyLocal", true ).toBool() ); - mSimplifyDrawingPanel->setVisible( mSimplifyDrawingSlider->value() > 0 ); - mSimplifyDrawingPx->setText( QString( "(%1 px)" ).arg( 1.0f + 0.2f * mSimplifyDrawingSlider->value() ) ); // Slightly awkard here at the settings value is true to use QImage, // but the checkbox is true to use QPixmap @@ -1104,10 +1102,10 @@ void QgsOptions::saveOptions() if ( mSimplifyDrawingGroupBox->isChecked() ) { simplifyHints |= QgsVectorLayer::GeometrySimplification; - if ( mSimplifyDrawingSlider->value() > 0 ) simplifyHints |= QgsVectorLayer::AntialiasingSimplification; + if ( mSimplifyDrawingSpinBox->value() > 1 ) simplifyHints |= QgsVectorLayer::AntialiasingSimplification; } settings.setValue( "/qgis/simplifyDrawingHints", simplifyHints ); - settings.setValue( "/qgis/simplifyDrawingTol", 1.0f + 0.2f*mSimplifyDrawingSlider->value() ); + settings.setValue( "/qgis/simplifyDrawingTol", mSimplifyDrawingSpinBox->value() ); settings.setValue( "/qgis/simplifyLocal", !mSimplifyDrawingAtProvider->isChecked() ); // project @@ -2087,10 +2085,3 @@ void QgsOptions::saveDefaultDatumTransformations() s.endGroup(); } - -void QgsOptions::on_mSimplifyDrawingSlider_valueChanged( int value ) -{ - mSimplifyDrawingPanel->setVisible( value > 0 ); - mSimplifyDrawingPx->setText( QString( "(%1 px)" ).arg( 1.0f + 0.2f * value ) ); -} - diff --git a/src/app/qgsoptions.h b/src/app/qgsoptions.h index 04ba4e2813f1..b6a4880a9903 100644 --- a/src/app/qgsoptions.h +++ b/src/app/qgsoptions.h @@ -240,8 +240,6 @@ class APP_EXPORT QgsOptions : public QgsOptionsDialogBase, private Ui::QgsOption void on_mRemoveDefaultTransformButton_clicked(); void on_mAddDefaultTransformButton_clicked(); - void on_mSimplifyDrawingSlider_valueChanged( int value ); - private: QStringList i18nList(); void initContrastEnhancement( QComboBox *cbox, QString name, QString defaultVal ); diff --git a/src/app/qgsvectorlayerproperties.cpp b/src/app/qgsvectorlayerproperties.cpp index 17e34d80c2cd..10e85da780ae 100644 --- a/src/app/qgsvectorlayerproperties.cpp +++ b/src/app/qgsvectorlayerproperties.cpp @@ -395,9 +395,7 @@ void QgsVectorLayerProperties::syncToLayer( void ) // get simplify drawing configuration const QgsVectorSimplifyMethod& simplifyMethod = layer->simplifyMethod(); mSimplifyDrawingGroupBox->setChecked( simplifyMethod.simplifyHints() != QgsVectorLayer::NoSimplification ); - mSimplifyDrawingSlider->setValue(( int )( 5.0f * ( simplifyMethod.threshold() - 1 ) ) ); - mSimplifyDrawingPanel->setVisible( mSimplifyDrawingSlider->value() > 0 ); - mSimplifyDrawingPx->setText( QString( "(%1 px)" ).arg( 1.0f + 0.2f * mSimplifyDrawingSlider->value() ) ); + mSimplifyDrawingSpinBox->setValue( simplifyMethod.threshold() ); if ( !( layer->dataProvider()->capabilities() & QgsVectorDataProvider::SimplifyGeometries ) ) { @@ -553,11 +551,11 @@ void QgsVectorLayerProperties::apply() if ( mSimplifyDrawingGroupBox->isChecked() ) { simplifyHints |= QgsVectorLayer::GeometrySimplification; - if ( mSimplifyDrawingSlider->value() > 0 ) simplifyHints |= QgsVectorLayer::AntialiasingSimplification; + if ( mSimplifyDrawingSpinBox->value() > 1 ) simplifyHints |= QgsVectorLayer::AntialiasingSimplification; } QgsVectorSimplifyMethod simplifyMethod = layer->simplifyMethod(); simplifyMethod.setSimplifyHints( simplifyHints ); - simplifyMethod.setThreshold( 1.0f + 0.2f*mSimplifyDrawingSlider->value() ); + simplifyMethod.setThreshold( mSimplifyDrawingSpinBox->value() ); simplifyMethod.setForceLocalOptimization( !mSimplifyDrawingAtProvider->isChecked() ); layer->setSimplifyMethod( simplifyMethod ); @@ -1100,12 +1098,6 @@ void QgsVectorLayerProperties::on_mMaximumScaleSetCurrentPushButton_clicked() cbMaximumScale->setScale( 1.0 / QgisApp::instance()->mapCanvas()->mapRenderer()->scale() ); } -void QgsVectorLayerProperties::on_mSimplifyDrawingSlider_valueChanged( int value ) -{ - mSimplifyDrawingPanel->setVisible( value > 0 ); - mSimplifyDrawingPx->setText( QString( "(%1 px)" ).arg( 1.0f + 0.2f * value ) ); -} - void QgsVectorLayerProperties::on_mSimplifyDrawingGroupBox_toggled( bool checked ) { if ( !( layer->dataProvider()->capabilities() & QgsVectorDataProvider::SimplifyGeometries ) ) diff --git a/src/app/qgsvectorlayerproperties.h b/src/app/qgsvectorlayerproperties.h index 8df2d9af4784..552a01a39c44 100644 --- a/src/app/qgsvectorlayerproperties.h +++ b/src/app/qgsvectorlayerproperties.h @@ -119,7 +119,6 @@ class APP_EXPORT QgsVectorLayerProperties : public QgsOptionsDialogBase, private void on_mMinimumScaleSetCurrentPushButton_clicked(); void on_mMaximumScaleSetCurrentPushButton_clicked(); - void on_mSimplifyDrawingSlider_valueChanged( int value ); void on_mSimplifyDrawingGroupBox_toggled( bool checked ); signals: diff --git a/src/core/qgsfeatureiterator.cpp b/src/core/qgsfeatureiterator.cpp index 71806e0c8253..38ba93e326c3 100644 --- a/src/core/qgsfeatureiterator.cpp +++ b/src/core/qgsfeatureiterator.cpp @@ -83,7 +83,11 @@ bool QgsAbstractFeatureIterator::nextFeatureFilterFids( QgsFeature& f ) void QgsAbstractFeatureIterator::ref() { - // prepare if required the simplification of geometries to fetch + // Prepare if required the simplification of geometries to fetch: + // This code runs here because of 'prepareSimplification()' is virtual and it can be overrided + // in inherited iterators who change the default behavior. + // It would be better to call this method in the constructor enabling virtual-calls as it is described by example at: + // http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctor-idiom.html if ( refs == 0 ) { prepareSimplification( mRequest.simplifyMethod() ); diff --git a/src/core/qgsfeatureiterator.h b/src/core/qgsfeatureiterator.h index 86926b9bfcd0..1ad21ee0044d 100644 --- a/src/core/qgsfeatureiterator.h +++ b/src/core/qgsfeatureiterator.h @@ -96,7 +96,7 @@ class CORE_EXPORT QgsAbstractFeatureIterator //! this iterator runs local simplification bool mLocalSimplification; - //! returns whether the iterator can simplify on provider side the geometries to fetch using the specified method type + //! returns whether the iterator supports simplify geometries on provider side virtual bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const; //! simplify the specified geometry if it was configured diff --git a/src/core/qgsvectorlayerfeatureiterator.h b/src/core/qgsvectorlayerfeatureiterator.h index d00bc8e05e09..1a39276a6de6 100644 --- a/src/core/qgsvectorlayerfeatureiterator.h +++ b/src/core/qgsvectorlayerfeatureiterator.h @@ -122,7 +122,7 @@ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureItera //! optional object to locally simplify edited (changed or added) geometries fetched by this feature iterator QgsAbstractGeometrySimplifier* mEditGeometrySimplifier; - //! returns whether the iterator can simplify on provider side the geometries to fetch using the specified method type + //! returns whether the iterator supports simplify geometries on provider side virtual bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const; }; diff --git a/src/providers/ogr/qgsogrfeatureiterator.h b/src/providers/ogr/qgsogrfeatureiterator.h index 156b0355538d..d7cf25fc66fc 100644 --- a/src/providers/ogr/qgsogrfeatureiterator.h +++ b/src/providers/ogr/qgsogrfeatureiterator.h @@ -65,7 +65,7 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIterator //! optional object to simplify OGR-geometries fecthed by this feature iterator QgsOgrAbstractGeometrySimplifier* mGeometrySimplifier; - //! returns whether the iterator can simplify on provider side the geometries to fetch using the specified method type + //! returns whether the iterator supports simplify geometries on provider side virtual bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const; }; diff --git a/src/providers/postgres/qgspostgresfeatureiterator.h b/src/providers/postgres/qgspostgresfeatureiterator.h index fa4e9da53aba..532b6bebeea9 100644 --- a/src/providers/postgres/qgspostgresfeatureiterator.h +++ b/src/providers/postgres/qgspostgresfeatureiterator.h @@ -70,7 +70,7 @@ class QgsPostgresFeatureIterator : public QgsAbstractFeatureIterator static const int sFeatureQueueSize; private: - //! returns whether the iterator can simplify on provider side the geometries to fetch using the specified method type + //! returns whether the iterator supports simplify geometries on provider side virtual bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const; }; diff --git a/src/ui/qgsoptionsbase.ui b/src/ui/qgsoptionsbase.ui index a9b7772d4fbe..c460a1038b9f 100644 --- a/src/ui/qgsoptionsbase.ui +++ b/src/ui/qgsoptionsbase.ui @@ -1684,209 +1684,79 @@ - Simplify geometries by default + Enable feature simplication by default for newly added layers true - + - - - 0 - 0 - + + <b>Note:</b> Feature simplification may speed up rendering but can result in rendering inconsistencies + + + + - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If checked, new vector layers added to the map will automatically use geometry simplification to speed up rendering. The simplification applies only during rendering of the layer and does not modify the layer geometry.</p></body></html> + Simplification threshold (higher values result in more simplification): - - true + + 2 + + + + + + + 2 + + + 1 + + + 5 + + + 0.20 + + + 1.0 + + + Higher values result in more simplification + + + + + + + pixels 2 - - - - Advanced settings + + + + Qt::Horizontal - - vectormeta + + + 20 + 20 + + + + + + + + Runs on provider side, otherwise it will execute once obtained the geometry from data source - - - - - Simplification runs on provider side, otherwise it will execute once obtained the geometry from data source. - - - - - - - Simplification threshold (higher values result in more simplification): - - - 2 - - - - - - - - 130 - 16777215 - - - - - 130 - 16777215 - - - - Higher values result in more simplification - - - 0 - - - 20 - - - 0 - - - true - - - Qt::Horizontal - - - false - - - false - - - - - - - (0 px) - - - 2 - - - - - - - Qt::Horizontal - - - - 20 - 20 - - - - - - - - - 0 - 70 - - - - - 16777215 - 16777215 - - - - QFrame::Box - - - QFrame::Raised - - - - - 10 - 0 - 60 - 67 - - - - - 0 - 0 - - - - - 60 - 67 - - - - - 40 - 40 - - - - Qt::LeftToRight - - - false - - - - - - :/images/themes/default/mIconWarn.png - - - false - - - - - - 45 - 8 - 411 - 51 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><span style=" font-size:8pt; font-weight:600;">Warning:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> Increasing this threshold may speed up rendering, but may result in gaps </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> or topological errors in the layer display.</span></p></body></html> - - - - - diff --git a/src/ui/qgsvectorlayerpropertiesbase.ui b/src/ui/qgsvectorlayerpropertiesbase.ui index 067052b82597..c7b54e5b69b2 100644 --- a/src/ui/qgsvectorlayerpropertiesbase.ui +++ b/src/ui/qgsvectorlayerpropertiesbase.ui @@ -949,206 +949,75 @@ true - - - - - 0 - 0 - + + + + <b>Note:</b> Feature simplification may speed up rendering but can result in rendering inconsistencies + + + + - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Note:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enabling this option simplifies geometries in this layer to improve rendering speed. The simplification applies only during rendering of the layer and does not modify the layer geometry.</p></body></html> - - - true + Simplification threshold (higher values result in more simplification): 2 - - - - Advanced settings + + + + 2 - - vectormeta + + 1 + + + 5 + + + 0.20 + + + 1.0 + + + Higher values result in more simplification - - - - - Simplification runs on provider side, otherwise it will execute once obtained the geometry from data source. - - - - - - - Simplification threshold (higher values result in more simplification): - - - 2 - - - - - - - - 130 - 16777215 - - - - - 130 - 16777215 - - - - Higher values result in more simplification - - - 0 - - - 20 - - - 0 - - - true - - - Qt::Horizontal - - - false - - - false - - - - - - - (0 px) - - - 2 - - - - - - - Qt::Horizontal - - - - 20 - 20 - - - - - - - - - 0 - 70 - - - - - 16777215 - 16777215 - - - - QFrame::Box - - - QFrame::Raised - - - - - 10 - 0 - 60 - 67 - - - - - 0 - 0 - - - - - 60 - 67 - - - - - 40 - 40 - - - - Qt::LeftToRight - - - false - - - - - - :/images/themes/default/mIconWarn.png - - - false - - - - - - 45 - 8 - 411 - 51 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span><span style=" font-size:8pt; font-weight:600;">Warning:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> Increasing this threshold may speed up rendering, but may result in gaps </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> or topological errors in the layer display.</span></p></body></html> - - - - - - + + + + + pixels + + + 2 + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + + + + + Runs on provider side, otherwise it will execute once obtained the geometry from data source + + + From c79cafc8c59776aad4066f94429a5a1868295c4e Mon Sep 17 00:00:00 2001 From: Alvaro Huarte Date: Wed, 15 Jan 2014 08:40:43 +0100 Subject: [PATCH 24/24] #8725-R: minor changes --- python/core/qgssimplifymethod.sip | 3 +++ src/core/qgssimplifymethod.cpp | 6 ++++++ src/core/qgssimplifymethod.h | 3 +++ src/providers/postgres/qgspostgresfeatureiterator.cpp | 2 +- src/ui/qgsoptionsbase.ui | 2 +- src/ui/qgsvectorlayerpropertiesbase.ui | 2 +- 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/python/core/qgssimplifymethod.sip b/python/core/qgssimplifymethod.sip index 55db7bb01daf..d053badbf934 100644 --- a/python/core/qgssimplifymethod.sip +++ b/python/core/qgssimplifymethod.sip @@ -29,6 +29,9 @@ class QgsSimplifyMethod /** Gets the tolerance of simplification */ double tolerance() const; + /** Returns the optimal tolerance for Douglas-Peucker simplification algorithms */ + double toleranceForDouglasPeuckerAlgorithms() const; + /** Sets whether the simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries */ void setForceLocalOptimization( bool localOptimization ); /** Gets whether the simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries */ diff --git a/src/core/qgssimplifymethod.cpp b/src/core/qgssimplifymethod.cpp index b3a6e89b74f5..29c402d9d3f7 100644 --- a/src/core/qgssimplifymethod.cpp +++ b/src/core/qgssimplifymethod.cpp @@ -53,6 +53,12 @@ void QgsSimplifyMethod::setForceLocalOptimization( bool localOptimization ) { mForceLocalOptimization = localOptimization; } + +double QgsSimplifyMethod::toleranceForDouglasPeuckerAlgorithms() const +{ + //TODO: define more precise value, now, it is experimental but conservative + return mTolerance / 5.0; +} QgsAbstractGeometrySimplifier* QgsSimplifyMethod::createGeometrySimplifier( const QgsSimplifyMethod& simplifyMethod ) { diff --git a/src/core/qgssimplifymethod.h b/src/core/qgssimplifymethod.h index 2143ffbaf191..4d8442886041 100644 --- a/src/core/qgssimplifymethod.h +++ b/src/core/qgssimplifymethod.h @@ -48,6 +48,9 @@ class CORE_EXPORT QgsSimplifyMethod //! Gets the tolerance of simplification inline double tolerance() const { return mTolerance; } + //! Returns the optimal tolerance for Douglas-Peucker simplification algorithms + double toleranceForDouglasPeuckerAlgorithms() const; + //! Sets whether the simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries void setForceLocalOptimization( bool localOptimization ); //! Gets whether the simplification executes after fetch the geometries from provider, otherwise it executes, when supported, in provider before fetch the geometries diff --git a/src/providers/postgres/qgspostgresfeatureiterator.cpp b/src/providers/postgres/qgspostgresfeatureiterator.cpp index da8dac128c6b..2cadc8fba939 100644 --- a/src/providers/postgres/qgspostgresfeatureiterator.cpp +++ b/src/providers/postgres/qgspostgresfeatureiterator.cpp @@ -309,7 +309,7 @@ bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause ) double tolerance = simplifyMethod.methodType() == QgsSimplifyMethod::OptimizeForRendering ? - simplifyMethod.tolerance() / 5.0f /* experimental */ + simplifyMethod.toleranceForDouglasPeuckerAlgorithms() : simplifyMethod.tolerance(); diff --git a/src/ui/qgsoptionsbase.ui b/src/ui/qgsoptionsbase.ui index c460a1038b9f..c1f3fd8bdead 100644 --- a/src/ui/qgsoptionsbase.ui +++ b/src/ui/qgsoptionsbase.ui @@ -1755,7 +1755,7 @@ - Runs on provider side, otherwise it will execute once obtained the geometry from data source + Simplify on provider side if possible diff --git a/src/ui/qgsvectorlayerpropertiesbase.ui b/src/ui/qgsvectorlayerpropertiesbase.ui index c7b54e5b69b2..468b6a7c6826 100644 --- a/src/ui/qgsvectorlayerpropertiesbase.ui +++ b/src/ui/qgsvectorlayerpropertiesbase.ui @@ -1014,7 +1014,7 @@ - Runs on provider side, otherwise it will execute once obtained the geometry from data source + Simplify on provider side if possible