QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsmaptopixelgeometrysimplifier.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmaptopixelgeometrysimplifier.cpp
3  ---------------------
4  begin : December 2013
5  copyright : (C) 2013 by Alvaro Huarte
6  email : http://wiki.osgeo.org/wiki/Alvaro_Huarte
7
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16
17 #include <limits>
18
20 #include "qgsapplication.h"
21 #include "qgslogger.h"
22
23
24 QgsMapToPixelSimplifier::QgsMapToPixelSimplifier( int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm )
25  : mSimplifyFlags( simplifyFlags )
26  , mSimplifyAlgorithm( simplifyAlgorithm )
27  , mTolerance( tolerance )
28 {
29 }
30
32 {
33 }
34
36 // Helper simplification methods
37
39 float QgsMapToPixelSimplifier::calculateLengthSquared2D( double x1, double y1, double x2, double y2 )
40 {
41  float vx = static_cast< float >( x2 - x1 );
42  float vy = static_cast< float >( y2 - y1 );
43
44  return ( vx * vx ) + ( vy * vy );
45 }
46
48 bool QgsMapToPixelSimplifier::equalSnapToGrid( double x1, double y1, double x2, double y2, double gridOriginX, double gridOriginY, float gridInverseSizeXY )
49 {
50  int grid_x1 = qRound(( x1 - gridOriginX ) * gridInverseSizeXY );
51  int grid_x2 = qRound(( x2 - gridOriginX ) * gridInverseSizeXY );
52  if ( grid_x1 != grid_x2 ) return false;
53
54  int grid_y1 = qRound(( y1 - gridOriginY ) * gridInverseSizeXY );
55  int grid_y2 = qRound(( y2 - gridOriginY ) * gridInverseSizeXY );
56  if ( grid_y1 != grid_y2 ) return false;
57
58  return true;
59 }
60
62 inline static QgsRectangle calculateBoundingBox( QGis::WkbType wkbType, QgsConstWkbPtr wkbPtr, int numPoints )
63 {
64  QgsRectangle r;
65  r.setMinimal();
66
67  int skipZM = ( QGis::wkbDimensions( wkbType ) - 2 ) * sizeof( double );
68  Q_ASSERT( skipZM >= 0 );
69
70  for ( int i = 0; i < numPoints; ++i )
71  {
72  double x, y;
73  wkbPtr >> x >> y;
74  wkbPtr += skipZM;
75  r.combineExtentWith( x, y );
76  }
77
78  return r;
79 }
80
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
106
109  QGis::WkbType wkbType,
110  QgsConstWkbPtr sourceWkbPtr,
111  QgsWkbPtr targetWkbPtr,
112  int &targetWkbSize,
113  const QgsRectangle &envelope, bool writeHeader )
114 {
115  QgsWkbPtr savedTargetWkb( targetWkbPtr );
116  unsigned int geometryType = QGis::singleType( QGis::flatType( wkbType ) );
117
118  int skipZM = ( QGis::wkbDimensions( wkbType ) - 2 ) * sizeof( double );
119  Q_ASSERT( skipZM >= 0 );
120
121  // If the geometry is already minimal skip the generalization
122  int minimumSize = geometryType == QGis::WKBLineString ? 4 + 2 * ( 2 * sizeof( double ) + skipZM ) : 8 + 5 * ( 2 * sizeof( double ) + skipZM );
123
125  minimumSize += 5;
126
127  if ( sourceWkbPtr.remaining() <= minimumSize )
128  {
129  targetWkbSize = 0;
130  return false;
131  }
132
133  double x1 = envelope.xMinimum();
134  double y1 = envelope.yMinimum();
135  double x2 = envelope.xMaximum();
136  double y2 = envelope.yMaximum();
137
138  // Write the main header of the geometry
140  {
141  targetWkbPtr << ( char ) QgsApplication::endian() << geometryType;
142
143  if ( geometryType == QGis::WKBPolygon ) // numRings
144  {
145  targetWkbPtr << 1;
146  }
147  }
148
149  // Write the generalized geometry
150  if ( geometryType == QGis::WKBLineString )
151  {
152  targetWkbPtr << 2 << x1 << y1 << x2 << y2;
153  }
154  else
155  {
156  targetWkbPtr << 5 << x1 << y1 << x2 << y1 << x2 << y2 << x1 << y2 << x1 << y1;
157  }
158
159  targetWkbSize += targetWkbPtr - savedTargetWkb;
160
161  return true;
162 }
163
165 bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
166  int simplifyFlags,
168  QGis::WkbType wkbType,
169  QgsConstWkbPtr sourceWkbPtr,
170  QgsWkbPtr targetWkbPtr,
171  int &targetWkbSize,
172  const QgsRectangle &envelope, double map2pixelTol,
173  bool writeHeader, bool isaLinearRing )
174 {
175  bool isGeneralizable = true;
176  bool result = false;
177
178  // Save initial WKB settings to use when the simplification creates invalid geometries
179  QgsConstWkbPtr sourcePrevWkbPtr( sourceWkbPtr );
180  QgsWkbPtr targetPrevWkbPtr( targetWkbPtr );
181  int targetWkbPrevSize = targetWkbSize;
182
183  // Can replace the geometry by its BBOX ?
185  isGeneralizableByMapBoundingBox( envelope, map2pixelTol ) )
186  {
187  isGeneralizable = generalizeWkbGeometryByBoundingBox( wkbType, sourceWkbPtr, targetWkbPtr, targetWkbSize, envelope, writeHeader );
188  if ( isGeneralizable )
189  return true;
190  }
191
193  isGeneralizable = false;
194
195  // Write the main header of the geometry
197  {
199
200  targetWkbPtr << ( char ) QgsApplication::endian() << QgsWKBTypes::flatType( geometryType );
201
202  targetWkbSize += targetWkbPtr - targetPrevWkbPtr;
203  }
204
205  unsigned int flatType = QGis::flatType( wkbType );
206
207  // Write the geometry
208  if ( flatType == QGis::WKBLineString || isaLinearRing )
209  {
210  QgsWkbPtr savedTargetWkbPtr( targetWkbPtr );
211  double x = 0.0, y = 0.0, lastX = 0, lastY = 0;
212  QgsRectangle r;
213  r.setMinimal();
214
215  int skipZM = ( QGis::wkbDimensions( wkbType ) - 2 ) * sizeof( double );
216  Q_ASSERT( skipZM >= 0 );
217
218  int numPoints;
219  sourceWkbPtr >> numPoints;
220
221  if ( numPoints <= ( isaLinearRing ? 5 : 2 ) )
222  isGeneralizable = false;
223
224  QgsWkbPtr numPtr( targetWkbPtr );
225
226  int numTargetPoints = 0;
227  targetWkbPtr << numTargetPoints;
228  targetWkbSize += 4;
229
230  bool isLongSegment;
231  bool hasLongSegments = false; //-> To avoid replace the simplified geometry by its BBOX when there are 'long' segments.
233
234  // Check whether the LinearRing is really closed.
235  if ( isaLinearRing )
236  {
237  QgsConstWkbPtr checkPtr( sourceWkbPtr );
238
239  double x1, y1, x2, y2;
240
241  checkPtr >> x1 >> y1;
242  checkPtr += skipZM + ( numPoints - 2 ) * ( 2 * sizeof( double ) + skipZM );
243  checkPtr >> x2 >> y2;
244
245  isaLinearRing = qgsDoubleNear( x1, x2 ) && qgsDoubleNear( y1, y2 );
246  }
247
248  // Process each vertex...
249  if ( simplifyAlgorithm == SnapToGrid )
250  {
251  double gridOriginX = envelope.xMinimum();
252  double gridOriginY = envelope.yMinimum();
253
254  // Use a factor for the maximum displacement distance for simplification, similar as GeoServer does
255  float gridInverseSizeXY = map2pixelTol != 0 ? ( float )( 1.0f / ( 0.8 * map2pixelTol ) ) : 0.0f;
256
257  for ( int i = 0; i < numPoints; ++i )
258  {
259  sourceWkbPtr >> x >> y;
260  sourceWkbPtr += skipZM;
261
262  if ( i == 0 ||
263  !isGeneralizable ||
264  !equalSnapToGrid( x, y, lastX, lastY, gridOriginX, gridOriginY, gridInverseSizeXY ) ||
265  ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
266  {
267  targetWkbPtr << x << y;
268  lastX = x;
269  lastY = y;
270  numTargetPoints++;
271  }
272
273  r.combineExtentWith( x, y );
274  }
275  }
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  }
310  else
311  {
312  map2pixelTol *= map2pixelTol; //-> Use mappixelTol for 'LengthSquare' calculations.
313
314  for ( int i = 0; i < numPoints; ++i )
315  {
316  sourceWkbPtr >> x >> y;
317  sourceWkbPtr += skipZM;
318
319  isLongSegment = false;
320
321  if ( i == 0 ||
322  !isGeneralizable ||
323  ( isLongSegment = ( calculateLengthSquared2D( x, y, lastX, lastY ) > map2pixelTol ) ) ||
324  ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
325  {
326  targetWkbPtr << x << y;
327  lastX = x;
328  lastY = y;
329  numTargetPoints++;
330
331  hasLongSegments |= isLongSegment;
332  }
333
334  r.combineExtentWith( x, y );
335  }
336  }
337
338  QgsWkbPtr nextPointPtr( targetWkbPtr );
339
340  targetWkbPtr = savedTargetWkbPtr;
341  targetWkbPtr += sizeof( int );
342
343  if ( numTargetPoints < ( isaLinearRing ? 4 : 2 ) )
344  {
345  // we simplified the geometry too much!
346  if ( !hasLongSegments )
347  {
348  // approximate the geometry's shape by its bounding box
349  // (rect for linear ring / one segment for line string)
350  QgsWkbPtr tempWkbPtr( targetWkbPtr );
351  int targetWkbTempSize = targetWkbSize;
352
353  sourceWkbPtr = sourcePrevWkbPtr;
354  targetWkbPtr = targetPrevWkbPtr;
355  targetWkbSize = targetWkbPrevSize;
356  if ( generalizeWkbGeometryByBoundingBox( wkbType, sourceWkbPtr, targetWkbPtr, targetWkbSize, r, writeHeader ) )
357  return true;
358
359  targetWkbPtr = tempWkbPtr;
360  targetWkbSize = targetWkbTempSize;
361  }
362  else
363  {
364  // Bad luck! The simplified geometry is invalid and approximation by bounding box
365  // would create artifacts due to long segments.
366  // We will return invalid geometry and hope that other pieces of QGIS will survive that :-/
367  }
369  }
370
371  if ( isaLinearRing )
372  {
373  // make sure we keep the linear ring closed
374  targetWkbPtr << x << y;
375  if ( !qgsDoubleNear( lastX, x ) || !qgsDoubleNear( lastY, y ) )
376  {
377  nextPointPtr << x << y;
378  numTargetPoints++;
379  }
380  }
381
382  numPtr << numTargetPoints;
383  targetWkbSize += numTargetPoints * sizeof( double ) * 2;
384
385  result = !badLuck && numTargetPoints > 0;
386  }
387  else if ( flatType == QGis::WKBPolygon )
388  {
389  int numRings;
390  sourceWkbPtr >> numRings;
391  targetWkbPtr << numRings;
392  targetWkbSize += 4;
393
394  for ( int i = 0; i < numRings; ++i )
395  {
396  int numPoints_i;
397  sourceWkbPtr >> numPoints_i;
398
399  QgsRectangle envelope_i = numRings == 1 ? envelope : calculateBoundingBox( wkbType, sourceWkbPtr, numPoints_i );
400
401  sourceWkbPtr -= sizeof( int );
402
403  int sourceWkbSize_i = sizeof( int ) + numPoints_i * QGis::wkbDimensions( wkbType ) * sizeof( double );
404  int targetWkbSize_i = 0;
405
406  result |= simplifyWkbGeometry( simplifyFlags, simplifyAlgorithm, wkbType, sourceWkbPtr, targetWkbPtr, targetWkbSize_i, envelope_i, map2pixelTol, false, true );
407  sourceWkbPtr += sourceWkbSize_i;
408  targetWkbPtr += targetWkbSize_i;
409
410  targetWkbSize += targetWkbSize_i;
411  }
412  }
413  else if ( flatType == QGis::WKBMultiLineString || flatType == QGis::WKBMultiPolygon )
414  {
415  int numGeoms;
416  sourceWkbPtr >> numGeoms;
417  targetWkbPtr << numGeoms;
418  targetWkbSize += 4;
419
420  QgsConstWkbPtr sourceWkbPtr2( sourceWkbPtr );
421
422  for ( int i = 0; i < numGeoms; ++i )
423  {
424  int sourceWkbSize_i = 0;
425  int targetWkbSize_i = 0;
426
428
429  // ... calculate the wkb-size of the current child complex geometry
430  if ( flatType == QGis::WKBMultiLineString )
431  {
432  int numPoints_i;
433  sourceWkbPtr2 >> numPoints_i;
434
435  int wkbSize_i = numPoints_i * QGis::wkbDimensions( wkbType ) * sizeof( double );
436
437  sourceWkbSize_i += 9 + wkbSize_i;
438  sourceWkbPtr2 += wkbSize_i;
439  }
440  else
441  {
442  int numPrings_i;
443  sourceWkbPtr2 >> numPrings_i;
444  sourceWkbSize_i = 1 + 2 * sizeof( int );
445
446  for ( int j = 0; j < numPrings_i; ++j )
447  {
448  int numPoints_i;
449  sourceWkbPtr2 >> numPoints_i;
450
451  int wkbSize_i = numPoints_i * QGis::wkbDimensions( wkbType ) * sizeof( double );
452
453  sourceWkbSize_i += 4 + wkbSize_i;
454  sourceWkbPtr2 += wkbSize_i;
455  }
456  }
457  result |= simplifyWkbGeometry( simplifyFlags, simplifyAlgorithm, QGis::singleType( wkbType ), sourceWkbPtr, targetWkbPtr, targetWkbSize_i, envelope, map2pixelTol, true, false );
458  sourceWkbPtr += sourceWkbSize_i;
459  targetWkbPtr += targetWkbSize_i;
460
461  targetWkbSize += targetWkbSize_i;
462  }
463  }
464
465  return result;
466 }
467
469
471 bool QgsMapToPixelSimplifier::isGeneralizableByMapBoundingBox( const QgsRectangle& envelope, double map2pixelTol )
472 {
473  // Can replace the geometry by its BBOX ?
474  return envelope.width() < map2pixelTol && envelope.height() < map2pixelTol;
475 }
476
479 {
480  QgsGeometry* g = new QgsGeometry();
481
482  int wkbSize = geometry->wkbSize();
483  unsigned char* wkb = new unsigned char[ wkbSize ];
484  memcpy( wkb, geometry->asWkb(), wkbSize );
485  g->fromWkb( wkb, wkbSize );
487
488  return g;
489 }
490
493 {
494  int finalWkbSize = 0;
495
496  // Check whether the geometry can be simplified using the map2pixel context
497  QGis::GeometryType geometryType = geometry->type();
498  if ( !( geometryType == QGis::Line || geometryType == QGis::Polygon ) )
499  return false;
500
501  QgsRectangle envelope = geometry->boundingBox();
502  QGis::WkbType wkbType = geometry->wkbType();
503
504  QgsConstWkbPtr wkbPtr( geometry->asWkb(), geometry->wkbSize() );
505
506  unsigned char* targetWkb = new unsigned char[wkbPtr.remaining()];
507  memcpy( targetWkb, wkbPtr, wkbPtr.remaining() );
508  QgsWkbPtr targetWkbPtr( targetWkb, wkbPtr.remaining() );
509
510  try
511  {
512  if ( simplifyWkbGeometry( simplifyFlags, simplifyAlgorithm, wkbType, wkbPtr, targetWkbPtr, finalWkbSize, envelope, tolerance ) )
513  {
514  unsigned char *finalWkb = new unsigned char[finalWkbSize];
515  memcpy( finalWkb, targetWkb, finalWkbSize );
516  geometry->fromWkb( finalWkb, finalWkbSize );
517  delete [] targetWkb;
518  return true;
519  }
520  }
521  catch ( const QgsWkbException &e )
522  {
523  Q_UNUSED( e );
524  QgsDebugMsg( QString( "Exception thrown by simplifier: %1" ) .arg( e.what() ) );
525  }
526  delete [] targetWkb;
527  return false;
528 }
529
532 {
534 }
535
538 {
539  QgsWKBTypes::Type singleType = QgsWKBTypes::singleType( wkbType );
540  QgsWKBTypes::Type flatType = QgsWKBTypes::flatType( singleType );
541
542  // Check whether the geometry can be simplified using the map2pixel context
543  if ( flatType == QgsWKBTypes::Point )
544  return false;
545
546  bool isaLinearRing = flatType == QgsWKBTypes::Polygon;
547  int numPoints;
548  sourceWkbPtr >> numPoints;
549
550  // No simplify simple geometries
551  if ( numPoints <= ( isaLinearRing ? 6 : 3 ) )
552  return false;
553
554  QgsRectangle envelope = calculateBoundingBox( QGis::fromNewWkbType( singleType ), QgsConstWkbPtr( sourceWkbPtr ), numPoints );
555  sourceWkbPtr -= sizeof( int );
556
557  int targetWkbSize = 5 + sizeof( int ) + numPoints * ( 2 * sizeof( double ) );
558  unsigned char* targetWkb = new unsigned char[ targetWkbSize ];
559
561  try
562  {
563  QgsWkbPtr targetWkbPtr( targetWkb, targetWkbSize );
564  targetWkbPtr << ( char ) QgsApplication::endian() << flatType;
565  targetWkbSize = 5;
566
567  if ( simplifyWkbGeometry( simplifyFlags, simplifyAlgorithm, QGis::fromNewWkbType( singleType ), sourceWkbPtr, targetWkbPtr, targetWkbSize, envelope, tolerance, false, isaLinearRing ) )
568  {
569  QgsConstWkbPtr finalWkbPtr( targetWkb, targetWkbSize );
571  finalWkbPtr >> targetPoints;
572
573  int skipZM = ( QGis::wkbDimensions( QGis::fromNewWkbType( wkbType ) ) - 2 ) * sizeof( double );
574  sourceWkbPtr += sizeof( int ) + numPoints * ( 2 * sizeof( double ) + skipZM );
575
576  delete [] targetWkb;
577  return true;
578  }
579  }
580  catch ( const QgsWkbException &e )
581  {
582  QgsDebugMsg( QString( "Exception thrown by simplifier: %1" ) .arg( e.what() ) );
583  }
584  delete [] targetWkb;
585  return false;
586 }
587
589 bool QgsMapToPixelSimplifier::simplifyPoints( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints ) const
590 {
591  return simplifyPoints( wkbType, sourceWkbPtr, targetPoints, mSimplifyFlags, mTolerance, mSimplifyAlgorithm );
592 }
static WkbType flatType(WkbType type)
Map 2d+ to 2d type.
Definition: qgis.cpp:401
A rectangle specified with double values.
Definition: qgsrectangle.h:35
QGis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
GeometryType
Definition: qgis.h:115
static int wkbDimensions(WkbType type)
Definition: qgis.cpp:432
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer&#39;s length...
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
static QGis::WkbType fromNewWkbType(QgsWKBTypes::Type type)
Converts from new (post 2.10) WKB type (OGC) to old WKB type.
Definition: qgis.cpp:146
virtual bool simplifyGeometry(QgsGeometry *geometry) const override
Simplifies the specified geometry.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
virtual QgsGeometry * simplify(QgsGeometry *geometry) const override
Returns a simplified version the specified geometry.
WkbType
Used for symbology operations.
Definition: qgis.h:61
The simplification uses a grid (similar to ST_SnapToGrid) to remove duplicate points.
SimplifyAlgorithm
Types of simplification algorithms that can be used.
static endian_t endian()
Returns whether this machine uses big or little endian.
int wkbSize() const
Returns the size of the WKB in asWkb().
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:353
QString what() const
Definition: qgsexception.h:36
double * getPoint_internal(const POINTARRAY *inpts, int pointIndex)
static bool isGeneralizableByMapBoundingBox(const QgsRectangle &envelope, double map2pixelTol)
Returns whether the envelope can be replaced by its BBOX when is applied the specified map2pixel cont...
static bool equalSnapToGrid(double x1, double y1, double x2, double y2, double gridOriginX, double gridOriginY, float gridInverseSizeXY)
Returns whether the points belong to the same grid.
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
static QgsRectangle calculateBoundingBox(QGis::WkbType wkbType, QgsConstWkbPtr wkbPtr, int numPoints)
Returns the BBOX of the specified WKB-point stream.
The geometries can be fully simplified by its BoundingBox.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:207
int simplifyFlags() const
Gets the simplification hints of the vector layer managed.
The simplification gives each point in a line an importance weighting, so that least important points...
static float calculateLengthSquared2D(double x1, double y1, double x2, double y2)
Returns the squared 2D-distance of the vector defined by the two points specified.
const unsigned char * asWkb() const
Returns the buffer containing this geometry in WKB format.
QGis::GeometryType type() const
Returns type of the geometry as a QGis::GeometryType.
static WkbType singleType(WkbType type)
Map multi to single type.
Definition: qgis.cpp:359
double mTolerance
Distance tolerance for the simplification.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:202
virtual bool simplifyPoints(QgsWKBTypes::Type wkbType, QgsConstWkbPtr &sourceWkbPtr, QPolygonF &targetPoints) const
Simplifies the specified WKB-point array.
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:187
void combineExtentWith(const QgsRectangle &rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
int remaining() const
Definition: qgswkbptr.h:133
QgsMapToPixelSimplifier(int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm=Distance)
Constructor.
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
static bool generalizeWkbGeometryByBoundingBox(QGis::WkbType wkbType, QgsConstWkbPtr sourceWkbPtr, QgsWkbPtr targetWkbPtr, int &targetWkbSize, const QgsRectangle &envelope, bool writeHeader)
Generalize the WKB-geometry using the BBOX of the original geometry.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:192
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:366
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:197
int mSimplifyFlags
Current simplification flags.
SimplifyAlgorithm mSimplifyAlgorithm
Current algorithm.