@@ -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
4948bool 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
83108static 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.
0 commit comments