Skip to content

Commit 7e1d142

Browse files
committed
Add Visvalingam simplification algorithm
1 parent 734b8b4 commit 7e1d142

9 files changed

+509
-1
lines changed

python/core/qgsmaptopixelgeometrysimplifier.sip

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ class QgsMapToPixelSimplifier : QgsAbstractGeometrySimplifier
99
{
1010
Distance = 0, //!< The simplification uses the distance between points to remove duplicate points
1111
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
1213
};
1314

1415
QgsMapToPixelSimplifier( int simplifyFlags, double tolerance );

python/core/qgsvectorsimplifymethod.sip

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class QgsVectorSimplifyMethod
3434
{
3535
Distance = 0, //!< The simplification uses the distance between points to remove duplicate points
3636
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
3738
};
3839

3940
/** Sets the local simplification algorithm of the vector layer managed */

src/app/qgsoptions.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,7 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl )
616616
// Default local simplification algorithm
617617
mSimplifyAlgorithmComboBox->addItem( tr( "Distance" ), ( int )QgsVectorSimplifyMethod::Distance );
618618
mSimplifyAlgorithmComboBox->addItem( tr( "SnapToGrid" ), ( int )QgsVectorSimplifyMethod::SnapToGrid );
619+
mSimplifyAlgorithmComboBox->addItem( tr( "Visvalingam" ), ( int )QgsVectorSimplifyMethod::Visvalingam );
619620
mSimplifyAlgorithmComboBox->setCurrentIndex( mSimplifyAlgorithmComboBox->findData( mSettings->value( "/qgis/simplifyAlgorithm", 0 ).toInt() ) );
620621

621622
// Slightly awkard here at the settings value is true to use QImage,

src/app/qgsvectorlayerproperties.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ void QgsVectorLayerProperties::syncToLayer()
442442
// Default local simplification algorithm
443443
mSimplifyAlgorithmComboBox->addItem( tr( "Distance" ), ( int )QgsVectorSimplifyMethod::Distance );
444444
mSimplifyAlgorithmComboBox->addItem( tr( "SnapToGrid" ), ( int )QgsVectorSimplifyMethod::SnapToGrid );
445+
mSimplifyAlgorithmComboBox->addItem( tr( "Visvalingam" ), ( int )QgsVectorSimplifyMethod::Visvalingam );
445446
mSimplifyAlgorithmComboBox->setCurrentIndex( mSimplifyAlgorithmComboBox->findData(( int )simplifyMethod.simplifyAlgorithm() ) );
446447

447448
QStringList myScalesList = PROJECT_SCALES.split( ',' );

src/core/qgsmaptopixelgeometrysimplifier.cpp

+60-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ float QgsMapToPixelSimplifier::calculateLengthSquared2D( double x1, double y1, d
4444
return ( vx * vx ) + ( vy * vy );
4545
}
4646

47-
4847
//! Returns whether the points belong to the same grid
4948
bool QgsMapToPixelSimplifier::equalSnapToGrid( double x1, double y1, double x2, double y2, double gridOriginX, double gridOriginY, float gridInverseSizeXY )
5049
{
@@ -79,6 +78,32 @@ inline static QgsRectangle calculateBoundingBox( QGis::WkbType wkbType, QgsConst
7978
return r;
8079
}
8180

81+
//////////////////////////////////////////////////////////////////////////////////////////////
82+
// Helper simplification methods for Visvalingam method
83+
84+
// It uses a refactored code of the liblwgeom implementation:
85+
// https://github.com/postgis/postgis/blob/svn-trunk/liblwgeom/effectivearea.h
86+
// https://github.com/postgis/postgis/blob/svn-trunk/liblwgeom/effectivearea.c
87+
88+
#define LWDEBUG //
89+
#define LWDEBUGF //
90+
#define FP_MAX qMax
91+
#define FLAGS_GET_Z( flags ) ( ( flags ) & 0x01 )
92+
#define LW_MSG_MAXLEN 256
93+
#define lwalloc qgsMalloc
94+
#define lwfree qgsFree
95+
#define lwerror qWarning
96+
97+
#include "simplify/effectivearea.h"
98+
#include "simplify/effectivearea.c"
99+
100+
double* getPoint_internal( const POINTARRAY* inpts, int pointIndex )
101+
{
102+
return inpts->pointlist + ( pointIndex * inpts->dimension );
103+
}
104+
105+
//////////////////////////////////////////////////////////////////////////////////////////////
106+
82107
//! Generalize the WKB-geometry using the BBOX of the original geometry
83108
static bool generalizeWkbGeometryByBoundingBox(
84109
QGis::WkbType wkbType,
@@ -248,6 +273,40 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
248273
r.combineExtentWith( x, y );
249274
}
250275
}
276+
else if ( simplifyAlgorithm == Visvalingam )
277+
{
278+
map2pixelTol *= map2pixelTol; //-> Use mappixelTol for 'Area' calculations.
279+
280+
POINTARRAY inpts;
281+
inpts.pointlist = ( double* )( const unsigned char* )sourceWkbPtr;
282+
inpts.dimension = QGis::wkbDimensions( wkbType );
283+
inpts.npoints = numPoints;
284+
inpts.flags = 0;
285+
286+
EFFECTIVE_AREAS* ea;
287+
ea = initiate_effectivearea( &inpts );
288+
289+
int set_area = 0;
290+
ptarray_calc_areas( ea, isaLinearRing ? 4 : 2, set_area, map2pixelTol );
291+
292+
for ( int i = 0; i < numPoints; ++i )
293+
{
294+
if ( ea->res_arealist[ i ] > map2pixelTol )
295+
{
296+
double* coord = getPoint_internal( &inpts, i );
297+
x = coord[ 0 ];
298+
y = coord[ 1 ];
299+
300+
targetWkbPtr << x << y;
301+
lastX = x;
302+
lastY = y;
303+
numTargetPoints++;
304+
}
305+
}
306+
destroy_effectivearea( ea );
307+
308+
sourceWkbPtr += numPoints * ( inpts.dimension * sizeof( double ) );
309+
}
251310
else
252311
{
253312
map2pixelTol *= map2pixelTol; //-> Use mappixelTol for 'LengthSquare' calculations.

src/core/qgsmaptopixelgeometrysimplifier.h

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class CORE_EXPORT QgsMapToPixelSimplifier : public QgsAbstractGeometrySimplifier
3737
{
3838
Distance = 0, //!< The simplification uses the distance between points to remove duplicate points
3939
SnapToGrid = 1, //!< The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points
40+
Visvalingam = 2, //!< The simplification gives each point in a line an importance weighting, so that least important points are removed first
4041
};
4142

4243
QgsMapToPixelSimplifier( int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm = Distance );

src/core/qgsvectorsimplifymethod.h

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class CORE_EXPORT QgsVectorSimplifyMethod
4747
{
4848
Distance = 0, //!< The simplification uses the distance between points to remove duplicate points
4949
SnapToGrid = 1, //!< The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points
50+
Visvalingam = 2, //!< The simplification gives each point in a line an importance weighting, so that least important points are removed first
5051
};
5152

5253
/** Sets the local simplification algorithm of the vector layer managed */

0 commit comments

Comments
 (0)