Skip to content

Commit 01a733b

Browse files
committed
#8725R: fix collapsed polygons by ST_simplify in postgis
1 parent f6f0384 commit 01a733b

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

src/providers/postgres/qgspostgresfeatureiterator.cpp

+38-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
***************************************************************************/
1515
#include "qgspostgresfeatureiterator.h"
1616
#include "qgspostgresprovider.h"
17+
#include "qgsgeometry.h"
1718

1819
#include "qgslogger.h"
1920
#include "qgsmessagelog.h"
@@ -292,6 +293,7 @@ QString QgsPostgresFeatureIterator::whereClauseRect()
292293
bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause )
293294
{
294295
mFetchGeometry = !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && !P->mGeometryColumn.isNull();
296+
bool simplifyGeometry = false;
295297

296298
try
297299
{
@@ -305,7 +307,8 @@ bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause )
305307
? ( P->mConnectionRO->majorVersion() < 2 ? "simplify" : "st_simplify" )
306308
: ( P->mConnectionRO->majorVersion() < 2 ? "simplifypreservetopology" : "st_simplifypreservetopology" );
307309

308-
double tolerance = simplifyMethod.tolerance();
310+
double tolerance = simplifyMethod.tolerance() * 0.8; //-> Default factor for the maximum displacement distance for simplification, similar as GeoServer does
311+
simplifyGeometry = simplifyMethod.methodType() == QgsSimplifyMethod::OptimizeForRendering;
309312

310313
query += QString( "%1(%5(%2%3,%6),'%4')" )
311314
.arg( P->mConnectionRO->majorVersion() < 2 ? "asbinary" : "st_asbinary" )
@@ -366,6 +369,17 @@ bool QgsPostgresFeatureIterator::declareCursor( const QString& whereClause )
366369
query += delim + P->mConnectionRO->fieldExpression( P->field( idx ) );
367370
}
368371

372+
// query BBOX of geometries to redefine the geometries collapsed by ST_Simplify()
373+
if ( simplifyGeometry && !( P->mConnectionRO->majorVersion() >= 2 && P->mConnectionRO->minorVersion() >= 1 ) && QGis::flatType( QGis::singleType( P->geometryType() ) ) == QGis::WKBPolygon )
374+
{
375+
query += QString( ",%1(%5(%2)%3,'%4')" )
376+
.arg( P->mConnectionRO->majorVersion() < 2 ? "asbinary" : "st_asbinary" )
377+
.arg( P->quotedIdentifier( P->mGeometryColumn ) )
378+
.arg( P->mSpatialColType == sctGeography ? "::geometry" : "" )
379+
.arg( P->endianString() )
380+
.arg( P->mConnectionRO->majorVersion() < 2 ? "envelope" : "st_envelope" );
381+
}
382+
369383
query += " FROM " + P->mQuery;
370384

371385
if ( !whereClause.isEmpty() )
@@ -589,6 +603,29 @@ bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int
589603
getFeatureAttribute( idx, queryResult, row, col, feature );
590604
}
591605

606+
// fix collapsed geometries by ST_Simplify() using the BBOX fetched from the current query
607+
const QgsSimplifyMethod& simplifyMethod = mRequest.simplifyMethod();
608+
if ( mFetchGeometry && !simplifyMethod.forceLocalOptimization() && simplifyMethod.methodType() == QgsSimplifyMethod::OptimizeForRendering && QGis::flatType( QGis::singleType( P->geometryType() ) ) == QGis::WKBPolygon )
609+
{
610+
QgsGeometry* geometry = feature.geometry();
611+
612+
if ( !( P->mConnectionRO->majorVersion() >= 2 && P->mConnectionRO->minorVersion() >= 1 ) && ( !geometry || geometry->length() == 0 ) )
613+
{
614+
int returnedLength = ::PQgetlength( queryResult.result(), row, col );
615+
616+
if ( returnedLength > 0 )
617+
{
618+
unsigned char *featureGeom = new unsigned char[returnedLength + 1];
619+
memcpy( featureGeom, PQgetvalue( queryResult.result(), row, col ), returnedLength );
620+
memset( featureGeom + returnedLength, 0, 1 );
621+
622+
QgsGeometry *envelope = new QgsGeometry();
623+
envelope->fromWkb( featureGeom, returnedLength + 1 );
624+
feature.setGeometry( envelope );
625+
}
626+
}
627+
}
628+
592629
return true;
593630
}
594631
catch ( QgsPostgresProvider::PGFieldNotFound )

0 commit comments

Comments
 (0)