Skip to content
Permalink
Browse files

Merge pull request #2900 from ahuarte47/Issue_QPainterSimplification

[Bugfix] QPainter simplification (fixes #14301)
  • Loading branch information
nyalldawson committed May 27, 2016
2 parents cbbc535 + 6969a1a commit d4a482b982b6748a1812efa0ef075b65bf668ba4
Showing with 1,088 additions and 668 deletions.
  1. +1 −1 python/core/qgsclipper.sip
  2. +27 −2 python/core/qgsmaptopixelgeometrysimplifier.sip
  3. +1 −1 python/core/qgssimplifymethod.sip
  4. +18 −0 python/core/qgsvectorsimplifymethod.sip
  5. +17 −3 python/core/symbology-ng/qgsrendererv2.sip
  6. +3 −3 python/core/symbology-ng/qgssymbolv2.sip
  7. +7 −0 src/app/qgsoptions.cpp
  8. +7 −0 src/app/qgsvectorlayerproperties.cpp
  9. +2 −0 src/core/CMakeLists.txt
  10. +30 −1 src/core/geometry/qgswkbptr.cpp
  11. +10 −0 src/core/geometry/qgswkbptr.h
  12. +48 −0 src/core/geometry/qgswkbsimplifierptr.cpp
  13. +61 −0 src/core/geometry/qgswkbsimplifierptr.h
  14. +13 −6 src/core/qgsclipper.cpp
  15. +1 −1 src/core/qgsclipper.h
  16. +1 −36 src/core/qgsfeatureiterator.cpp
  17. +0 −9 src/core/qgsfeatureiterator.h
  18. +195 −30 src/core/qgsmaptopixelgeometrysimplifier.cpp
  19. +30 −3 src/core/qgsmaptopixelgeometrysimplifier.h
  20. +41 −0 src/core/qgspallabeling.cpp
  21. +1 −1 src/core/qgssimplifymethod.cpp
  22. +3 −3 src/core/qgssimplifymethod.h
  23. +3 −0 src/core/qgsvectorlayer.cpp
  24. +1 −49 src/core/qgsvectorlayerfeatureiterator.cpp
  25. +1 −6 src/core/qgsvectorlayerfeatureiterator.h
  26. +1 −2 src/core/qgsvectorlayerrenderer.cpp
  27. +2 −0 src/core/qgsvectorsimplifymethod.cpp
  28. +22 −0 src/core/qgsvectorsimplifymethod.h
  29. +361 −0 src/core/simplify/effectivearea.c
  30. +84 −0 src/core/simplify/effectivearea.h
  31. +2 −1 src/core/symbology-ng/qgspointdisplacementrenderer.cpp
  32. +3 −3 src/core/symbology-ng/qgsrendererv2.cpp
  33. +17 −3 src/core/symbology-ng/qgsrendererv2.h
  34. +26 −28 src/core/symbology-ng/qgssymbolv2.cpp
  35. +3 −3 src/core/symbology-ng/qgssymbolv2.h
  36. +1 −1 src/providers/ogr/CMakeLists.txt
  37. +0 −62 src/providers/ogr/qgsogrfeatureiterator.cpp
  38. +0 −10 src/providers/ogr/qgsogrfeatureiterator.h
  39. +0 −285 src/providers/ogr/qgsogrgeometrysimplifier.cpp
  40. +0 −95 src/providers/ogr/qgsogrgeometrysimplifier.h
  41. +0 −10 src/providers/ogr/qgsogrprovider.cpp
  42. +20 −3 src/ui/qgsoptionsbase.ui
  43. +20 −3 src/ui/qgsvectorlayerpropertiesbase.ui
  44. +3 −1 tests/src/core/testqgsmaptopixelgeometrysimplifier.cpp
  45. +0 −2 tests/src/python/test_provider_shapefile.py
  46. +1 −1 tests/src/python/test_qgsgeometry.py
  47. BIN ...ontrol_images/expected_geometrygenerator_buffer_lines/expected_geometrygenerator_buffer_lines.png
  48. BIN ...l_images/expected_geometrygenerator_buffer_lines/expected_geometrygenerator_buffer_lines_mask.png
  49. BIN tests/testdata/control_images/expected_geometrygenerator_mixed/expected_geometrygenerator_mixed.png
  50. BIN ...estdata/control_images/expected_geometrygenerator_mixed/expected_geometrygenerator_mixed_mask.png
@@ -56,5 +56,5 @@ class QgsClipper
@param wkb pointer to the start of the line wkb
@param clipExtent clipping bounds
@param line out: clipped line coordinates*/
static QgsConstWkbPtr clippedLineWKB( QgsConstWkbPtr wkb, const QgsRectangle& clipExtent, QPolygonF& line );
static QgsConstWkbPtr clippedLineWKB( QgsConstWkbPtr& wkb, const QgsRectangle& clipExtent, QPolygonF& line );
};
@@ -4,7 +4,16 @@ class QgsMapToPixelSimplifier : QgsAbstractGeometrySimplifier
#include "qgsmaptopixelgeometrysimplifier.h"
%End
public:
QgsMapToPixelSimplifier( int simplifyFlags, double tolerance );
//! Types of simplification algorithms that can be used
enum SimplifyAlgorithm
{
Distance = 0, //!< The simplification uses the distance between points to remove duplicate points
SnapToGrid = 1, //!< The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points
Visvalingam = 2, //!< The simplification gives each point in a line an importance weighting, so that least important points are removed first
};

//! Constructor
QgsMapToPixelSimplifier( int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm = Distance );
virtual ~QgsMapToPixelSimplifier();

//! Applicable simplification flags
@@ -20,15 +29,28 @@ class QgsMapToPixelSimplifier : QgsAbstractGeometrySimplifier
//! 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 whether the points belong to the same grid
static bool equalSnapToGrid( double x1, double y1, double x2, double y2, double gridOriginX, double gridOriginY, float gridInverseSizeXY );

public:
//! Gets the simplification hints of the vector layer managed
int simplifyFlags() const;
//! Sets the simplification hints of the vector layer managed
void setSimplifyFlags( int simplifyFlags );

//! Gets the local simplification algorithm of the vector layer managed
SimplifyAlgorithm simplifyAlgorithm() const;
//! Sets the local simplification algorithm of the vector layer managed
void setSimplifyAlgorithm( SimplifyAlgorithm simplifyAlgorithm );

//! Returns a simplified version the specified geometry
virtual QgsGeometry* simplify( QgsGeometry* geometry ) const;
//! Simplifies the specified geometry
virtual bool simplifyGeometry( QgsGeometry* geometry ) const;

//! Simplifies the specified WKB-point array
virtual bool simplifyPoints( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints ) const;

// MapToPixel simplification helper methods
public:

@@ -39,6 +61,9 @@ class QgsMapToPixelSimplifier : QgsAbstractGeometrySimplifier
bool isGeneralizableByMapBoundingBox( const QgsRectangle& envelope ) const;

//! Simplifies the geometry when is applied the specified map2pixel context
static bool simplifyGeometry( QgsGeometry* geometry, int simplifyFlags, double tolerance );
static bool simplifyGeometry( QgsGeometry* geometry, int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm = Distance );

//! Simplifies the WKB-point array when is applied the specified map2pixel context
static bool simplifyPoints( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints, int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm = Distance );

};
@@ -26,7 +26,7 @@ class QgsSimplifyMethod

//! Sets the tolerance of simplification in map units. Represents the maximum distance in map units between two coordinates which can be considered equal.
void setTolerance( double tolerance );
//! Gets the tolerance of simplification in map units . Represents the maximum distance in map units between two coordinates which can be considered equal.
//! Gets the tolerance of simplification in map units. Represents the maximum distance in map units between two coordinates which can be considered equal.
double tolerance() const;

//! Sets the simplification threshold in pixels. Represents the maximum distance in pixels between two coordinates which can be considered equal.
@@ -29,6 +29,24 @@ class QgsVectorSimplifyMethod
/** Gets the simplification hints of the vector layer managed */
QFlags<QgsVectorSimplifyMethod::SimplifyHint> simplifyHints() const;

/** Types of local simplification algorithms that can be used */
enum SimplifyAlgorithm
{
Distance = 0, //!< The simplification uses the distance between points to remove duplicate points
SnapToGrid = 1, //!< The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points
Visvalingam = 2, //!< The simplification gives each point in a line an importance weighting, so that least important points are removed first
};

/** Sets the local simplification algorithm of the vector layer managed */
void setSimplifyAlgorithm( const SimplifyAlgorithm& simplifyAlgorithm );
/** Gets the local simplification algorithm of the vector layer managed */
SimplifyAlgorithm simplifyAlgorithm() const;

/** Sets the tolerance of simplification in map units. Represents the maximum distance in map units between two coordinates which can be considered equal */
void setTolerance( double tolerance );
/** Gets the tolerance of simplification in map units. Represents the maximum distance in map units between two coordinates which can be considered equal */
double tolerance() const;

/** Sets the simplification threshold of the vector layer managed */
void setThreshold( float threshold );
/** Gets the simplification threshold of the vector layer managed */
@@ -403,9 +403,23 @@ class QgsFeatureRendererV2
//! render editing vertex marker for a polygon
void renderVertexMarkerPolygon( QPolygonF& pts, QList<QPolygonF>* rings, QgsRenderContext& context );

static QgsConstWkbPtr _getPoint( QPointF& pt, QgsRenderContext& context, QgsConstWkbPtr wkb );
static QgsConstWkbPtr _getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
static QgsConstWkbPtr _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
/**
* Creates a point in screen coordinates from a wkb string in map
* coordinates
*/
static QgsConstWkbPtr _getPoint( QPointF& pt, QgsRenderContext& context, QgsConstWkbPtr& wkb );

/**
* Creates a line string in screen coordinates from a wkb string in map
* coordinates
*/
static QgsConstWkbPtr _getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr& wkb, bool clipToExtent = true );

/**
* Creates a polygon in screen coordinates from a wkb string in map
* coordinates
*/
static QgsConstWkbPtr _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, QgsConstWkbPtr& wkb, bool clipToExtent = true );

void setScaleMethodToSymbol( QgsSymbolV2* symbol, int scaleMethod );

@@ -228,19 +228,19 @@ class QgsSymbolV2
* Creates a point in screen coordinates from a wkb string in map
* coordinates
*/
static QgsConstWkbPtr _getPoint( QPointF& pt, QgsRenderContext& context, QgsConstWkbPtr wkb );
static QgsConstWkbPtr _getPoint( QPointF& pt, QgsRenderContext& context, QgsConstWkbPtr& wkb );

/**
* Creates a line string in screen coordinates from a wkb string in map
* coordinates
*/
static QgsConstWkbPtr _getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
static QgsConstWkbPtr _getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr& wkb, bool clipToExtent = true );

/**
* Creates a polygon in screen coordinates from a wkb string in map
* coordinates
*/
static QgsConstWkbPtr _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
static QgsConstWkbPtr _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, QgsConstWkbPtr& wkb, bool clipToExtent = true );

/**
* Retrieve a cloned list of all layers that make up this symbol.
@@ -613,6 +613,12 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl )
doubleSpinBoxMagnifierDefault->setSuffix( "%" );
doubleSpinBoxMagnifierDefault->setValue( mSettings->value( "/qgis/magnifier_level", 100 ).toInt() );

// Default local simplification algorithm
mSimplifyAlgorithmComboBox->addItem( tr( "Distance" ), ( int )QgsVectorSimplifyMethod::Distance );
mSimplifyAlgorithmComboBox->addItem( tr( "SnapToGrid" ), ( int )QgsVectorSimplifyMethod::SnapToGrid );
mSimplifyAlgorithmComboBox->addItem( tr( "Visvalingam" ), ( int )QgsVectorSimplifyMethod::Visvalingam );
mSimplifyAlgorithmComboBox->setCurrentIndex( mSimplifyAlgorithmComboBox->findData( mSettings->value( "/qgis/simplifyAlgorithm", 0 ).toInt() ) );

// Slightly awkard here at the settings value is true to use QImage,
// but the checkbox is true to use QPixmap
chkAddedVisibility->setChecked( mSettings->value( "/qgis/new_layers_visible", true ).toBool() );
@@ -1212,6 +1218,7 @@ void QgsOptions::saveOptions()
if ( mSimplifyDrawingSpinBox->value() > 1 ) simplifyHints |= QgsVectorSimplifyMethod::AntialiasingSimplification;
}
mSettings->setValue( "/qgis/simplifyDrawingHints", ( int ) simplifyHints );
mSettings->setValue( "/qgis/simplifyAlgorithm", mSimplifyAlgorithmComboBox->itemData( mSimplifyAlgorithmComboBox->currentIndex() ).toInt() );
mSettings->setValue( "/qgis/simplifyDrawingTol", mSimplifyDrawingSpinBox->value() );
mSettings->setValue( "/qgis/simplifyLocal", !mSimplifyDrawingAtProvider->isChecked() );
mSettings->setValue( "/qgis/simplifyMaxScale", 1.0 / mSimplifyMaximumScaleComboBox->scale() );
@@ -439,6 +439,12 @@ void QgsVectorLayerProperties::syncToLayer()
mSimplifyDrawingGroupBox->setEnabled( false );
}

// Default local simplification algorithm
mSimplifyAlgorithmComboBox->addItem( tr( "Distance" ), ( int )QgsVectorSimplifyMethod::Distance );
mSimplifyAlgorithmComboBox->addItem( tr( "SnapToGrid" ), ( int )QgsVectorSimplifyMethod::SnapToGrid );
mSimplifyAlgorithmComboBox->addItem( tr( "Visvalingam" ), ( int )QgsVectorSimplifyMethod::Visvalingam );
mSimplifyAlgorithmComboBox->setCurrentIndex( mSimplifyAlgorithmComboBox->findData(( int )simplifyMethod.simplifyAlgorithm() ) );

QStringList myScalesList = PROJECT_SCALES.split( ',' );
myScalesList.append( "1:1" );
mSimplifyMaximumScaleComboBox->updateScales( myScalesList );
@@ -625,6 +631,7 @@ void QgsVectorLayerProperties::apply()
}
QgsVectorSimplifyMethod simplifyMethod = mLayer->simplifyMethod();
simplifyMethod.setSimplifyHints( simplifyHints );
simplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( mSimplifyAlgorithmComboBox->itemData( mSimplifyAlgorithmComboBox->currentIndex() ).toInt() ) );
simplifyMethod.setThreshold( mSimplifyDrawingSpinBox->value() );
simplifyMethod.setForceLocalOptimization( !mSimplifyDrawingAtProvider->isChecked() );
simplifyMethod.setMaximumScale( 1.0 / mSimplifyMaximumScaleComboBox->scale() );
@@ -352,6 +352,7 @@ SET(QGIS_CORE_SRCS
geometry/qgspolygonv2.cpp
geometry/qgswkbptr.cpp
geometry/qgswkbtypes.cpp
geometry/qgswkbsimplifierptr.cpp

${CMAKE_CURRENT_BINARY_DIR}/qgscontexthelp_texts.cpp
${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp
@@ -836,6 +837,7 @@ SET(QGIS_CORE_HDRS
geometry/qgspointv2.h
geometry/qgswkbptr.h
geometry/qgswkbtypes.h
geometry/qgswkbsimplifierptr.h
)

IF (QT_MOBILITY_LOCATION_FOUND OR Qt5Positioning_FOUND)
@@ -32,6 +32,7 @@ QgsConstWkbPtr::QgsConstWkbPtr( const unsigned char *p, int size )
mP = const_cast< unsigned char * >( p );
mEnd = mP + size;
mEndianSwap = false;
mWkbType = QgsWKBTypes::Unknown;
}

QgsWKBTypes::Type QgsConstWkbPtr::readHeader() const
@@ -45,12 +46,40 @@ QgsWKBTypes::Type QgsConstWkbPtr::readHeader() const

int wkbType;
*this >> wkbType;
mWkbType = static_cast<QgsWKBTypes::Type>( wkbType );

return static_cast<QgsWKBTypes::Type>( wkbType );
return mWkbType;
}

void QgsConstWkbPtr::verifyBound( int size ) const
{
if ( !mP || mP + size > mEnd )
throw QgsWkbException( "wkb access out of bounds" );
}

const QgsConstWkbPtr &QgsConstWkbPtr::operator>>( QPointF &point ) const
{
read( point.rx() );
read( point.ry() );
return *this;
}

const QgsConstWkbPtr &QgsConstWkbPtr::operator>>( QPolygonF &points ) const
{
int skipZM = ( QgsWKBTypes::coordDimensions( mWkbType ) - 2 ) * sizeof( double );
Q_ASSERT( skipZM >= 0 );

unsigned int nPoints;
read( nPoints );

points.resize( nPoints );
QPointF* ptr = points.data();

for ( unsigned int i = 0; i < nPoints; ++i, ++ptr )
{
read( ptr->rx() );
read( ptr->ry() );
mP += skipZM;
}
return *this;
}
@@ -19,6 +19,7 @@
#include "qgsapplication.h"
#include "qgis.h"
#include "qgsexception.h"
#include "qpolygon.h"

/** \ingroup core
* * Custom exception class for Wkb related exceptions.
@@ -89,12 +90,16 @@ class CORE_EXPORT QgsWkbPtr

class CORE_EXPORT QgsConstWkbPtr
{
protected:
mutable unsigned char *mP;
unsigned char *mEnd;
mutable bool mEndianSwap;
mutable QgsWKBTypes::Type mWkbType;

//! Verify bounds
void verifyBound( int size ) const;

//! Read a value
template<typename T> void read( T& v ) const
{
verifyBound( sizeof v );
@@ -114,6 +119,11 @@ class CORE_EXPORT QgsConstWkbPtr
inline const QgsConstWkbPtr &operator>>( unsigned int &v ) const { read( v ); return *this; }
inline const QgsConstWkbPtr &operator>>( char &v ) const { read( v ); return *this; }

//! Read a point
virtual const QgsConstWkbPtr &operator>>( QPointF &point ) const;
//! Read a point array
virtual const QgsConstWkbPtr &operator>>( QPolygonF &points ) const;

inline void operator+=( int n ) { verifyBound( n ); mP += n; }
inline void operator-=( int n ) { mP -= n; }

@@ -0,0 +1,48 @@
/***************************************************************************
qgswkbsimplifierptr.cpp
---------------------
begin : February 2016
copyright : (C) 2016 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 "qgswkbsimplifierptr.h"
#include "qgsgeometry.h"
#include "qgssimplifymethod.h"
#include "qgsmaptopixelgeometrysimplifier.h"

QgsConstWkbSimplifierPtr::QgsConstWkbSimplifierPtr( const unsigned char *p, int size, const QgsVectorSimplifyMethod &simplifyMethod )
: QgsConstWkbPtr( p, size )
, mSimplifyMethod( simplifyMethod )
{
}

const QgsConstWkbPtr &QgsConstWkbSimplifierPtr::operator>>( QPointF &point ) const
{
return QgsConstWkbPtr::operator>>( point );
}

const QgsConstWkbPtr &QgsConstWkbSimplifierPtr::operator>>( QPolygonF &points ) const
{
if ( mSimplifyMethod.simplifyHints() != QgsVectorSimplifyMethod::NoSimplification && mSimplifyMethod.forceLocalOptimization() )
{
int simplifyHints = mSimplifyMethod.simplifyHints() | QgsMapToPixelSimplifier::SimplifyEnvelope;
QgsMapToPixelSimplifier::SimplifyAlgorithm simplifyAlgorithm = static_cast< QgsMapToPixelSimplifier::SimplifyAlgorithm >( mSimplifyMethod.simplifyAlgorithm() );

QgsConstWkbPtr wkbPtr = *this;

if ( QgsMapToPixelSimplifier::simplifyPoints( mWkbType, wkbPtr, points, simplifyHints, mSimplifyMethod.tolerance(), simplifyAlgorithm ) )
{
mP = const_cast< unsigned char * >(( const unsigned char * ) wkbPtr );
return *this;
}
}
QgsConstWkbPtr::operator>>( points );
return *this;
}

0 comments on commit d4a482b

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