21
21
#include " qgslogger.h"
22
22
23
23
24
- QgsMapToPixelSimplifier::QgsMapToPixelSimplifier ( int simplifyFlags, double tolerance )
24
+ QgsMapToPixelSimplifier::QgsMapToPixelSimplifier ( int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm )
25
25
: mSimplifyFlags( simplifyFlags )
26
26
, mTolerance( tolerance )
27
+ , mSimplifyAlgorithm( simplifyAlgorithm )
27
28
{
28
29
}
29
30
@@ -40,7 +41,22 @@ float QgsMapToPixelSimplifier::calculateLengthSquared2D( double x1, double y1, d
40
41
float vx = static_cast < float >( x2 - x1 );
41
42
float vy = static_cast < float >( y2 - y1 );
42
43
43
- return vx*vx + vy*vy;
44
+ return ( vx * vx ) + ( vy * vy );
45
+ }
46
+
47
+
48
+ // ! Returns whether the points belong to the same grid
49
+ bool QgsMapToPixelSimplifier::equalSnapToGrid ( double x1, double y1, double x2, double y2, double gridOriginX, double gridOriginY, float gridInverseSizeXY )
50
+ {
51
+ int grid_x1 = qRound (( x1 - gridOriginX ) * gridInverseSizeXY );
52
+ int grid_x2 = qRound (( x2 - gridOriginX ) * gridInverseSizeXY );
53
+ if ( grid_x1 != grid_x2 ) return false ;
54
+
55
+ int grid_y1 = qRound (( y1 - gridOriginY ) * gridInverseSizeXY );
56
+ int grid_y2 = qRound (( y2 - gridOriginY ) * gridInverseSizeXY );
57
+ if ( grid_y1 != grid_y2 ) return false ;
58
+
59
+ return true ;
44
60
}
45
61
46
62
// ! Returns the BBOX of the specified WKB-point stream
@@ -122,7 +138,9 @@ static bool generalizeWkbGeometryByBoundingBox(
122
138
123
139
// ! Simplify the WKB-geometry using the specified tolerance
124
140
bool QgsMapToPixelSimplifier::simplifyWkbGeometry (
125
- int simplifyFlags, QGis::WkbType wkbType,
141
+ int simplifyFlags,
142
+ SimplifyAlgorithm simplifyAlgorithm,
143
+ QGis::WkbType wkbType,
126
144
QgsConstWkbPtr sourceWkbPtr,
127
145
QgsWkbPtr targetWkbPtr,
128
146
int &targetWkbSize,
@@ -184,8 +202,6 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
184
202
targetWkbPtr << numTargetPoints;
185
203
targetWkbSize += 4 ;
186
204
187
- map2pixelTol *= map2pixelTol; // -> Use mappixelTol for 'LengthSquare' calculations.
188
-
189
205
bool isLongSegment;
190
206
bool hasLongSegments = false ; // -> To avoid replace the simplified geometry by its BBOX when there are 'long' segments.
191
207
bool badLuck = false ;
@@ -205,27 +221,59 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
205
221
}
206
222
207
223
// Process each vertex...
208
- for ( int i = 0 ; i < numPoints; ++i )
224
+ if ( simplifyAlgorithm == SnapToGrid )
209
225
{
210
- sourceWkbPtr >> x >> y ;
211
- sourceWkbPtr += skipZM ;
226
+ double gridOriginX = envelope. xMinimum () ;
227
+ double gridOriginY = envelope. yMinimum () ;
212
228
213
- isLongSegment = false ;
229
+ // Use a factor for the maximum displacement distance for simplification, similar as GeoServer does
230
+ float gridInverseSizeXY = map2pixelTol != 0 ? ( float )( 1 .0f / ( 0.8 * map2pixelTol ) ) : 0 .0f ;
214
231
215
- if ( i == 0 ||
216
- !isGeneralizable ||
217
- ( isLongSegment = ( calculateLengthSquared2D ( x, y, lastX, lastY ) > map2pixelTol ) ) ||
218
- ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
232
+ for ( int i = 0 ; i < numPoints; ++i )
219
233
{
220
- targetWkbPtr << x << y;
221
- lastX = x;
222
- lastY = y;
223
- numTargetPoints++;
234
+ sourceWkbPtr >> x >> y;
235
+ sourceWkbPtr += skipZM;
236
+
237
+ if ( i == 0 ||
238
+ !isGeneralizable ||
239
+ !equalSnapToGrid ( x, y, lastX, lastY, gridOriginX, gridOriginY, gridInverseSizeXY ) ||
240
+ ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
241
+ {
242
+ targetWkbPtr << x << y;
243
+ lastX = x;
244
+ lastY = y;
245
+ numTargetPoints++;
246
+ }
224
247
225
- hasLongSegments |= isLongSegment ;
248
+ r. combineExtentWith ( x, y ) ;
226
249
}
250
+ }
251
+ else
252
+ {
253
+ map2pixelTol *= map2pixelTol; // -> Use mappixelTol for 'LengthSquare' calculations.
254
+
255
+ for ( int i = 0 ; i < numPoints; ++i )
256
+ {
257
+ sourceWkbPtr >> x >> y;
258
+ sourceWkbPtr += skipZM;
259
+
260
+ isLongSegment = false ;
227
261
228
- r.combineExtentWith ( x, y );
262
+ if ( i == 0 ||
263
+ !isGeneralizable ||
264
+ ( isLongSegment = ( calculateLengthSquared2D ( x, y, lastX, lastY ) > map2pixelTol ) ) ||
265
+ ( !isaLinearRing && ( i == 1 || i >= numPoints - 2 ) ) )
266
+ {
267
+ targetWkbPtr << x << y;
268
+ lastX = x;
269
+ lastY = y;
270
+ numTargetPoints++;
271
+
272
+ hasLongSegments |= isLongSegment;
273
+ }
274
+
275
+ r.combineExtentWith ( x, y );
276
+ }
229
277
}
230
278
231
279
QgsWkbPtr nextPointPtr ( targetWkbPtr );
@@ -296,7 +344,7 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
296
344
int sourceWkbSize_i = sizeof ( int ) + numPoints_i * QGis::wkbDimensions ( wkbType ) * sizeof ( double );
297
345
int targetWkbSize_i = 0 ;
298
346
299
- result |= simplifyWkbGeometry ( simplifyFlags, wkbType, sourceWkbPtr, targetWkbPtr, targetWkbSize_i, envelope_i, map2pixelTol, false , true );
347
+ result |= simplifyWkbGeometry ( simplifyFlags, simplifyAlgorithm, wkbType, sourceWkbPtr, targetWkbPtr, targetWkbSize_i, envelope_i, map2pixelTol, false , true );
300
348
sourceWkbPtr += sourceWkbSize_i;
301
349
targetWkbPtr += targetWkbSize_i;
302
350
@@ -347,7 +395,7 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry(
347
395
sourceWkbPtr2 += wkbSize_i;
348
396
}
349
397
}
350
- result |= simplifyWkbGeometry ( simplifyFlags, QGis::singleType ( wkbType ), sourceWkbPtr, targetWkbPtr, targetWkbSize_i, envelope, map2pixelTol, true , false );
398
+ result |= simplifyWkbGeometry ( simplifyFlags, simplifyAlgorithm, QGis::singleType ( wkbType ), sourceWkbPtr, targetWkbPtr, targetWkbSize_i, envelope, map2pixelTol, true , false );
351
399
sourceWkbPtr += sourceWkbSize_i;
352
400
targetWkbPtr += targetWkbSize_i;
353
401
@@ -376,13 +424,13 @@ QgsGeometry* QgsMapToPixelSimplifier::simplify( QgsGeometry* geometry ) const
376
424
unsigned char * wkb = new unsigned char [ wkbSize ];
377
425
memcpy ( wkb, geometry->asWkb (), wkbSize );
378
426
g->fromWkb ( wkb, wkbSize );
379
- simplifyGeometry ( g, mSimplifyFlags , mTolerance );
427
+ simplifyGeometry ( g, mSimplifyFlags , mTolerance , mSimplifyAlgorithm );
380
428
381
429
return g;
382
430
}
383
431
384
432
// ! Simplifies the geometry (Removing duplicated points) when is applied the specified map2pixel context
385
- bool QgsMapToPixelSimplifier::simplifyGeometry ( QgsGeometry *geometry, int simplifyFlags, double tolerance )
433
+ bool QgsMapToPixelSimplifier::simplifyGeometry ( QgsGeometry *geometry, int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm )
386
434
{
387
435
int finalWkbSize = 0 ;
388
436
@@ -402,7 +450,7 @@ bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry *geometry, int simpl
402
450
403
451
try
404
452
{
405
- if ( simplifyWkbGeometry ( simplifyFlags, wkbType, wkbPtr, targetWkbPtr, finalWkbSize, envelope, tolerance ) )
453
+ if ( simplifyWkbGeometry ( simplifyFlags, simplifyAlgorithm, wkbType, wkbPtr, targetWkbPtr, finalWkbSize, envelope, tolerance ) )
406
454
{
407
455
unsigned char *finalWkb = new unsigned char [finalWkbSize];
408
456
memcpy ( finalWkb, targetWkb, finalWkbSize );
@@ -423,11 +471,11 @@ bool QgsMapToPixelSimplifier::simplifyGeometry( QgsGeometry *geometry, int simpl
423
471
// ! Simplifies the geometry (Removing duplicated points) when is applied the specified map2pixel context
424
472
bool QgsMapToPixelSimplifier::simplifyGeometry ( QgsGeometry* geometry ) const
425
473
{
426
- return simplifyGeometry ( geometry, mSimplifyFlags , mTolerance );
474
+ return simplifyGeometry ( geometry, mSimplifyFlags , mTolerance , mSimplifyAlgorithm );
427
475
}
428
476
429
477
// ! Simplifies the WKB-point array (Removing duplicated points) when is applied the specified map2pixel context
430
- bool QgsMapToPixelSimplifier::simplifyPoints ( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints, int simplifyFlags, double tolerance )
478
+ bool QgsMapToPixelSimplifier::simplifyPoints ( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints, int simplifyFlags, double tolerance, SimplifyAlgorithm simplifyAlgorithm )
431
479
{
432
480
QgsWKBTypes::Type singleType = QgsWKBTypes::singleType ( wkbType );
433
481
QgsWKBTypes::Type flatType = QgsWKBTypes::flatType ( singleType );
@@ -457,7 +505,7 @@ bool QgsMapToPixelSimplifier::simplifyPoints( QgsWKBTypes::Type wkbType, QgsCons
457
505
targetWkbPtr << ( char ) QgsApplication::endian () << flatType;
458
506
targetWkbSize = 5 ;
459
507
460
- if ( simplifyWkbGeometry ( simplifyFlags, QGis::fromNewWkbType ( singleType ), sourceWkbPtr, targetWkbPtr, targetWkbSize, envelope, tolerance, false , isaLinearRing ) )
508
+ if ( simplifyWkbGeometry ( simplifyFlags, simplifyAlgorithm, QGis::fromNewWkbType ( singleType ), sourceWkbPtr, targetWkbPtr, targetWkbSize, envelope, tolerance, false , isaLinearRing ) )
461
509
{
462
510
QgsConstWkbPtr finalWkbPtr ( targetWkb, targetWkbSize );
463
511
finalWkbPtr.readHeader ();
@@ -481,5 +529,5 @@ bool QgsMapToPixelSimplifier::simplifyPoints( QgsWKBTypes::Type wkbType, QgsCons
481
529
// ! Simplifies the specified WKB-point array
482
530
bool QgsMapToPixelSimplifier::simplifyPoints ( QgsWKBTypes::Type wkbType, QgsConstWkbPtr& sourceWkbPtr, QPolygonF& targetPoints ) const
483
531
{
484
- return simplifyPoints ( wkbType, sourceWkbPtr, targetPoints, mSimplifyFlags , mTolerance );
532
+ return simplifyPoints ( wkbType, sourceWkbPtr, targetPoints, mSimplifyFlags , mTolerance , mSimplifyAlgorithm );
485
533
}
0 commit comments