QGIS API Documentation  2.17.0-Master (2f94c66)
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 *
11  * it under the terms of the GNU General Public License as published by *
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 
124  if ( writeHeader )
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
139  if ( writeHeader )
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
196  if ( writeHeader )
197  {
198  QgsWKBTypes::Type geometryType = sourceWkbPtr.readHeader();
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.
232  bool badLuck = false;
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  }
368  badLuck = true;
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 
427  sourceWkbPtr2.readHeader();
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 );
570  finalWkbPtr.readHeader();
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
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
int remaining() const
Definition: qgswkbptr.h:133
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...
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:197
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
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.
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
QGis::GeometryType type() const
Returns type of the geometry as a QGis::GeometryType.
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.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:353
double * getPoint_internal(const POINTARRAY *inpts, int pointIndex)
QgsWKBTypes::Type readHeader() const
Definition: qgswkbptr.cpp:38
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.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:202
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:187
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.
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.
QGis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
int simplifyFlags() const
Gets the simplification hints of the vector layer managed.
static WkbType singleType(WkbType type)
Map multi to single type.
Definition: qgis.cpp:359
double mTolerance
Distance tolerance for the simplification.
void combineExtentWith(const QgsRectangle &rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
QString what() const
Definition: qgsexception.h:36
virtual bool simplifyPoints(QgsWKBTypes::Type wkbType, QgsConstWkbPtr &sourceWkbPtr, QPolygonF &targetPoints) const
Simplifies the specified WKB-point array.
int wkbSize() const
Returns the size of the WKB in asWkb().
QgsMapToPixelSimplifier(int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm=Distance)
Constructor.
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.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:366
int mSimplifyFlags
Current simplification flags.
SimplifyAlgorithm mSimplifyAlgorithm
Current algorithm.
The geometries can be simplified using the current map2pixel context state.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:207
const unsigned char * asWkb() const
Returns the buffer containing this geometry in WKB format.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:192
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:212
static Type singleType(Type type)
Returns the single type for a WKB type.
Definition: qgswkbtypes.h:114