Skip to content

Commit d4a482b

Browse files
committed
Merge pull request #2900 from ahuarte47/Issue_QPainterSimplification
[Bugfix] QPainter simplification (fixes #14301)
2 parents cbbc535 + 6969a1a commit d4a482b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1088
-668
lines changed

python/core/qgsclipper.sip

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,5 @@ class QgsClipper
5656
@param wkb pointer to the start of the line wkb
5757
@param clipExtent clipping bounds
5858
@param line out: clipped line coordinates*/
59-
static QgsConstWkbPtr clippedLineWKB( QgsConstWkbPtr wkb, const QgsRectangle& clipExtent, QPolygonF& line );
59+
static QgsConstWkbPtr clippedLineWKB( QgsConstWkbPtr& wkb, const QgsRectangle& clipExtent, QPolygonF& line );
6060
};

python/core/qgsmaptopixelgeometrysimplifier.sip

+27-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@ class QgsMapToPixelSimplifier : QgsAbstractGeometrySimplifier
44
#include "qgsmaptopixelgeometrysimplifier.h"
55
%End
66
public:
7-
QgsMapToPixelSimplifier( int simplifyFlags, double tolerance );
7+
//! Types of simplification algorithms that can be used
8+
enum SimplifyAlgorithm
9+
{
10+
Distance = 0, //!< The simplification uses the distance between points to remove duplicate points
11+
SnapToGrid = 1, //!< The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points
12+
Visvalingam = 2, //!< The simplification gives each point in a line an importance weighting, so that least important points are removed first
13+
};
14+
15+
//! Constructor
16+
QgsMapToPixelSimplifier( int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm = Distance );
817
virtual ~QgsMapToPixelSimplifier();
918

1019
//! Applicable simplification flags
@@ -20,15 +29,28 @@ class QgsMapToPixelSimplifier : QgsAbstractGeometrySimplifier
2029
//! Returns the squared 2D-distance of the vector defined by the two points specified
2130
static float calculateLengthSquared2D( double x1, double y1, double x2, double y2 );
2231

32+
//! Returns whether the points belong to the same grid
33+
static bool equalSnapToGrid( double x1, double y1, double x2, double y2, double gridOriginX, double gridOriginY, float gridInverseSizeXY );
34+
2335
public:
36+
//! Gets the simplification hints of the vector layer managed
2437
int simplifyFlags() const;
38+
//! Sets the simplification hints of the vector layer managed
2539
void setSimplifyFlags( int simplifyFlags );
2640

41+
//! Gets the local simplification algorithm of the vector layer managed
42+
SimplifyAlgorithm simplifyAlgorithm() const;
43+
//! Sets the local simplification algorithm of the vector layer managed
44+
void setSimplifyAlgorithm( SimplifyAlgorithm simplifyAlgorithm );
45+
2746
//! Returns a simplified version the specified geometry
2847
virtual QgsGeometry* simplify( QgsGeometry* geometry ) const;
2948
//! Simplifies the specified geometry
3049
virtual bool simplifyGeometry( QgsGeometry* geometry ) const;
3150

51+
//! Simplifies the specified WKB-point array
52+
virtual bool simplifyPoints( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints ) const;
53+
3254
// MapToPixel simplification helper methods
3355
public:
3456

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

4163
//! Simplifies the geometry when is applied the specified map2pixel context
42-
static bool simplifyGeometry( QgsGeometry* geometry, int simplifyFlags, double tolerance );
64+
static bool simplifyGeometry( QgsGeometry* geometry, int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm = Distance );
65+
66+
//! Simplifies the WKB-point array when is applied the specified map2pixel context
67+
static bool simplifyPoints( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints, int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm = Distance );
4368

4469
};

python/core/qgssimplifymethod.sip

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class QgsSimplifyMethod
2626

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

3232
//! Sets the simplification threshold in pixels. Represents the maximum distance in pixels between two coordinates which can be considered equal.

python/core/qgsvectorsimplifymethod.sip

+18
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,24 @@ class QgsVectorSimplifyMethod
2929
/** Gets the simplification hints of the vector layer managed */
3030
QFlags<QgsVectorSimplifyMethod::SimplifyHint> simplifyHints() const;
3131

32+
/** Types of local simplification algorithms that can be used */
33+
enum SimplifyAlgorithm
34+
{
35+
Distance = 0, //!< The simplification uses the distance between points to remove duplicate points
36+
SnapToGrid = 1, //!< The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points
37+
Visvalingam = 2, //!< The simplification gives each point in a line an importance weighting, so that least important points are removed first
38+
};
39+
40+
/** Sets the local simplification algorithm of the vector layer managed */
41+
void setSimplifyAlgorithm( const SimplifyAlgorithm& simplifyAlgorithm );
42+
/** Gets the local simplification algorithm of the vector layer managed */
43+
SimplifyAlgorithm simplifyAlgorithm() const;
44+
45+
/** Sets the tolerance of simplification in map units. Represents the maximum distance in map units between two coordinates which can be considered equal */
46+
void setTolerance( double tolerance );
47+
/** Gets the tolerance of simplification in map units. Represents the maximum distance in map units between two coordinates which can be considered equal */
48+
double tolerance() const;
49+
3250
/** Sets the simplification threshold of the vector layer managed */
3351
void setThreshold( float threshold );
3452
/** Gets the simplification threshold of the vector layer managed */

python/core/symbology-ng/qgsrendererv2.sip

+17-3
Original file line numberDiff line numberDiff line change
@@ -403,9 +403,23 @@ class QgsFeatureRendererV2
403403
//! render editing vertex marker for a polygon
404404
void renderVertexMarkerPolygon( QPolygonF& pts, QList<QPolygonF>* rings, QgsRenderContext& context );
405405

406-
static QgsConstWkbPtr _getPoint( QPointF& pt, QgsRenderContext& context, QgsConstWkbPtr wkb );
407-
static QgsConstWkbPtr _getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
408-
static QgsConstWkbPtr _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
406+
/**
407+
* Creates a point in screen coordinates from a wkb string in map
408+
* coordinates
409+
*/
410+
static QgsConstWkbPtr _getPoint( QPointF& pt, QgsRenderContext& context, QgsConstWkbPtr& wkb );
411+
412+
/**
413+
* Creates a line string in screen coordinates from a wkb string in map
414+
* coordinates
415+
*/
416+
static QgsConstWkbPtr _getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr& wkb, bool clipToExtent = true );
417+
418+
/**
419+
* Creates a polygon in screen coordinates from a wkb string in map
420+
* coordinates
421+
*/
422+
static QgsConstWkbPtr _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, QgsConstWkbPtr& wkb, bool clipToExtent = true );
409423

410424
void setScaleMethodToSymbol( QgsSymbolV2* symbol, int scaleMethod );
411425

python/core/symbology-ng/qgssymbolv2.sip

+3-3
Original file line numberDiff line numberDiff line change
@@ -228,19 +228,19 @@ class QgsSymbolV2
228228
* Creates a point in screen coordinates from a wkb string in map
229229
* coordinates
230230
*/
231-
static QgsConstWkbPtr _getPoint( QPointF& pt, QgsRenderContext& context, QgsConstWkbPtr wkb );
231+
static QgsConstWkbPtr _getPoint( QPointF& pt, QgsRenderContext& context, QgsConstWkbPtr& wkb );
232232

233233
/**
234234
* Creates a line string in screen coordinates from a wkb string in map
235235
* coordinates
236236
*/
237-
static QgsConstWkbPtr _getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr wkb, bool clipToExtent = true );
237+
static QgsConstWkbPtr _getLineString( QPolygonF& pts, QgsRenderContext& context, QgsConstWkbPtr& wkb, bool clipToExtent = true );
238238

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

245245
/**
246246
* Retrieve a cloned list of all layers that make up this symbol.

src/app/qgsoptions.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,12 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl )
613613
doubleSpinBoxMagnifierDefault->setSuffix( "%" );
614614
doubleSpinBoxMagnifierDefault->setValue( mSettings->value( "/qgis/magnifier_level", 100 ).toInt() );
615615

616+
// Default local simplification algorithm
617+
mSimplifyAlgorithmComboBox->addItem( tr( "Distance" ), ( int )QgsVectorSimplifyMethod::Distance );
618+
mSimplifyAlgorithmComboBox->addItem( tr( "SnapToGrid" ), ( int )QgsVectorSimplifyMethod::SnapToGrid );
619+
mSimplifyAlgorithmComboBox->addItem( tr( "Visvalingam" ), ( int )QgsVectorSimplifyMethod::Visvalingam );
620+
mSimplifyAlgorithmComboBox->setCurrentIndex( mSimplifyAlgorithmComboBox->findData( mSettings->value( "/qgis/simplifyAlgorithm", 0 ).toInt() ) );
621+
616622
// Slightly awkard here at the settings value is true to use QImage,
617623
// but the checkbox is true to use QPixmap
618624
chkAddedVisibility->setChecked( mSettings->value( "/qgis/new_layers_visible", true ).toBool() );
@@ -1212,6 +1218,7 @@ void QgsOptions::saveOptions()
12121218
if ( mSimplifyDrawingSpinBox->value() > 1 ) simplifyHints |= QgsVectorSimplifyMethod::AntialiasingSimplification;
12131219
}
12141220
mSettings->setValue( "/qgis/simplifyDrawingHints", ( int ) simplifyHints );
1221+
mSettings->setValue( "/qgis/simplifyAlgorithm", mSimplifyAlgorithmComboBox->itemData( mSimplifyAlgorithmComboBox->currentIndex() ).toInt() );
12151222
mSettings->setValue( "/qgis/simplifyDrawingTol", mSimplifyDrawingSpinBox->value() );
12161223
mSettings->setValue( "/qgis/simplifyLocal", !mSimplifyDrawingAtProvider->isChecked() );
12171224
mSettings->setValue( "/qgis/simplifyMaxScale", 1.0 / mSimplifyMaximumScaleComboBox->scale() );

src/app/qgsvectorlayerproperties.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,12 @@ void QgsVectorLayerProperties::syncToLayer()
439439
mSimplifyDrawingGroupBox->setEnabled( false );
440440
}
441441

442+
// Default local simplification algorithm
443+
mSimplifyAlgorithmComboBox->addItem( tr( "Distance" ), ( int )QgsVectorSimplifyMethod::Distance );
444+
mSimplifyAlgorithmComboBox->addItem( tr( "SnapToGrid" ), ( int )QgsVectorSimplifyMethod::SnapToGrid );
445+
mSimplifyAlgorithmComboBox->addItem( tr( "Visvalingam" ), ( int )QgsVectorSimplifyMethod::Visvalingam );
446+
mSimplifyAlgorithmComboBox->setCurrentIndex( mSimplifyAlgorithmComboBox->findData(( int )simplifyMethod.simplifyAlgorithm() ) );
447+
442448
QStringList myScalesList = PROJECT_SCALES.split( ',' );
443449
myScalesList.append( "1:1" );
444450
mSimplifyMaximumScaleComboBox->updateScales( myScalesList );
@@ -625,6 +631,7 @@ void QgsVectorLayerProperties::apply()
625631
}
626632
QgsVectorSimplifyMethod simplifyMethod = mLayer->simplifyMethod();
627633
simplifyMethod.setSimplifyHints( simplifyHints );
634+
simplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( mSimplifyAlgorithmComboBox->itemData( mSimplifyAlgorithmComboBox->currentIndex() ).toInt() ) );
628635
simplifyMethod.setThreshold( mSimplifyDrawingSpinBox->value() );
629636
simplifyMethod.setForceLocalOptimization( !mSimplifyDrawingAtProvider->isChecked() );
630637
simplifyMethod.setMaximumScale( 1.0 / mSimplifyMaximumScaleComboBox->scale() );

src/core/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ SET(QGIS_CORE_SRCS
352352
geometry/qgspolygonv2.cpp
353353
geometry/qgswkbptr.cpp
354354
geometry/qgswkbtypes.cpp
355+
geometry/qgswkbsimplifierptr.cpp
355356

356357
${CMAKE_CURRENT_BINARY_DIR}/qgscontexthelp_texts.cpp
357358
${CMAKE_CURRENT_BINARY_DIR}/qgsexpression_texts.cpp
@@ -836,6 +837,7 @@ SET(QGIS_CORE_HDRS
836837
geometry/qgspointv2.h
837838
geometry/qgswkbptr.h
838839
geometry/qgswkbtypes.h
840+
geometry/qgswkbsimplifierptr.h
839841
)
840842

841843
IF (QT_MOBILITY_LOCATION_FOUND OR Qt5Positioning_FOUND)

src/core/geometry/qgswkbptr.cpp

+30-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ QgsConstWkbPtr::QgsConstWkbPtr( const unsigned char *p, int size )
3232
mP = const_cast< unsigned char * >( p );
3333
mEnd = mP + size;
3434
mEndianSwap = false;
35+
mWkbType = QgsWKBTypes::Unknown;
3536
}
3637

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

4647
int wkbType;
4748
*this >> wkbType;
49+
mWkbType = static_cast<QgsWKBTypes::Type>( wkbType );
4850

49-
return static_cast<QgsWKBTypes::Type>( wkbType );
51+
return mWkbType;
5052
}
5153

5254
void QgsConstWkbPtr::verifyBound( int size ) const
5355
{
5456
if ( !mP || mP + size > mEnd )
5557
throw QgsWkbException( "wkb access out of bounds" );
5658
}
59+
60+
const QgsConstWkbPtr &QgsConstWkbPtr::operator>>( QPointF &point ) const
61+
{
62+
read( point.rx() );
63+
read( point.ry() );
64+
return *this;
65+
}
66+
67+
const QgsConstWkbPtr &QgsConstWkbPtr::operator>>( QPolygonF &points ) const
68+
{
69+
int skipZM = ( QgsWKBTypes::coordDimensions( mWkbType ) - 2 ) * sizeof( double );
70+
Q_ASSERT( skipZM >= 0 );
71+
72+
unsigned int nPoints;
73+
read( nPoints );
74+
75+
points.resize( nPoints );
76+
QPointF* ptr = points.data();
77+
78+
for ( unsigned int i = 0; i < nPoints; ++i, ++ptr )
79+
{
80+
read( ptr->rx() );
81+
read( ptr->ry() );
82+
mP += skipZM;
83+
}
84+
return *this;
85+
}

src/core/geometry/qgswkbptr.h

+10
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "qgsapplication.h"
2020
#include "qgis.h"
2121
#include "qgsexception.h"
22+
#include "qpolygon.h"
2223

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

9091
class CORE_EXPORT QgsConstWkbPtr
9192
{
93+
protected:
9294
mutable unsigned char *mP;
9395
unsigned char *mEnd;
9496
mutable bool mEndianSwap;
97+
mutable QgsWKBTypes::Type mWkbType;
9598

99+
//! Verify bounds
96100
void verifyBound( int size ) const;
97101

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

122+
//! Read a point
123+
virtual const QgsConstWkbPtr &operator>>( QPointF &point ) const;
124+
//! Read a point array
125+
virtual const QgsConstWkbPtr &operator>>( QPolygonF &points ) const;
126+
117127
inline void operator+=( int n ) { verifyBound( n ); mP += n; }
118128
inline void operator-=( int n ) { mP -= n; }
119129

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/***************************************************************************
2+
qgswkbsimplifierptr.cpp
3+
---------------------
4+
begin : February 2016
5+
copyright : (C) 2016 by Alvaro Huarte
6+
email : http://wiki.osgeo.org/wiki/Alvaro_Huarte
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
#include "qgswkbsimplifierptr.h"
16+
#include "qgsgeometry.h"
17+
#include "qgssimplifymethod.h"
18+
#include "qgsmaptopixelgeometrysimplifier.h"
19+
20+
QgsConstWkbSimplifierPtr::QgsConstWkbSimplifierPtr( const unsigned char *p, int size, const QgsVectorSimplifyMethod &simplifyMethod )
21+
: QgsConstWkbPtr( p, size )
22+
, mSimplifyMethod( simplifyMethod )
23+
{
24+
}
25+
26+
const QgsConstWkbPtr &QgsConstWkbSimplifierPtr::operator>>( QPointF &point ) const
27+
{
28+
return QgsConstWkbPtr::operator>>( point );
29+
}
30+
31+
const QgsConstWkbPtr &QgsConstWkbSimplifierPtr::operator>>( QPolygonF &points ) const
32+
{
33+
if ( mSimplifyMethod.simplifyHints() != QgsVectorSimplifyMethod::NoSimplification && mSimplifyMethod.forceLocalOptimization() )
34+
{
35+
int simplifyHints = mSimplifyMethod.simplifyHints() | QgsMapToPixelSimplifier::SimplifyEnvelope;
36+
QgsMapToPixelSimplifier::SimplifyAlgorithm simplifyAlgorithm = static_cast< QgsMapToPixelSimplifier::SimplifyAlgorithm >( mSimplifyMethod.simplifyAlgorithm() );
37+
38+
QgsConstWkbPtr wkbPtr = *this;
39+
40+
if ( QgsMapToPixelSimplifier::simplifyPoints( mWkbType, wkbPtr, points, simplifyHints, mSimplifyMethod.tolerance(), simplifyAlgorithm ) )
41+
{
42+
mP = const_cast< unsigned char * >(( const unsigned char * ) wkbPtr );
43+
return *this;
44+
}
45+
}
46+
QgsConstWkbPtr::operator>>( points );
47+
return *this;
48+
}

0 commit comments

Comments
 (0)