Skip to content

Commit

Permalink
Merge pull request #1087 from ahuarte47/Issue_9360R
Browse files Browse the repository at this point in the history
Fix bug #9360-revival: fix whole layer not rendered (when simplify geometry activated; followup 3305a6c; fixes #9360)
  • Loading branch information
jef-n committed Jan 22, 2014
2 parents f2d0100 + f79dfa1 commit 12a463d
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 51 deletions.
26 changes: 20 additions & 6 deletions src/providers/ogr/qgsogrfeatureiterator.cpp
Expand Up @@ -109,31 +109,45 @@ bool QgsOgrFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simp
if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) && simplifyMethod.methodType() != QgsSimplifyMethod::NoSimplification && !simplifyMethod.forceLocalOptimization() )
{
QgsSimplifyMethod::MethodType methodType = simplifyMethod.methodType();
Q_UNUSED( methodType);

#if defined(GDAL_VERSION_NUM) && defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0)
if ( methodType == QgsSimplifyMethod::OptimizeForRendering )
{
int simplifyFlags = QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope;
mGeometrySimplifier = new QgsOgrMapToPixelSimplifier( simplifyFlags, simplifyMethod.tolerance() );
return true;
}
#endif
#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1900
else if ( methodType == QgsSimplifyMethod::PreserveTopology )
if ( methodType == QgsSimplifyMethod::PreserveTopology )
{
mGeometrySimplifier = new QgsOgrTopologyPreservingSimplifier( simplifyMethod.tolerance() );
return true;
}
#endif
else
{
QgsDebugMsg( QString( "Simplification method type (%1) is not recognised by OgrFeatureIterator class" ).arg( methodType ) );
}

QgsDebugMsg( QString( "Simplification method type (%1) is not recognised by OgrFeatureIterator class" ).arg( methodType ) );
}
return QgsAbstractFeatureIterator::prepareSimplification( simplifyMethod );
}

bool QgsOgrFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
{
return methodType == QgsSimplifyMethod::OptimizeForRendering || methodType == QgsSimplifyMethod::PreserveTopology;
#if defined(GDAL_VERSION_NUM) && defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0)
if ( methodType == QgsSimplifyMethod::OptimizeForRendering )
{
return true;
}
#endif
#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1900
if ( methodType == QgsSimplifyMethod::PreserveTopology )
{
return true;
}
#endif

return false;
}

bool QgsOgrFeatureIterator::fetchFeature( QgsFeature& feature )
Expand Down
135 changes: 92 additions & 43 deletions src/providers/ogr/qgsogrgeometrysimplifier.cpp
Expand Up @@ -25,6 +25,7 @@ QgsOgrAbstractGeometrySimplifier::~QgsOgrAbstractGeometrySimplifier()
/***************************************************************************/

#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1900

QgsOgrTopologyPreservingSimplifier::QgsOgrTopologyPreservingSimplifier( double tolerance )
: QgsTopologyPreservingSimplifier( tolerance )
{
Expand Down Expand Up @@ -59,22 +60,76 @@ bool QgsOgrTopologyPreservingSimplifier::simplifyGeometry( OGRGeometryH geometry

/***************************************************************************/

#if defined(GDAL_VERSION_NUM) && defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0)

QgsOgrMapToPixelSimplifier::QgsOgrMapToPixelSimplifier( int simplifyFlags, double map2pixelTol )
: QgsMapToPixelSimplifier( simplifyFlags, map2pixelTol )
, mPointBufferPtr( NULL )
, mPointBufferCount( 0 )
{
}

QgsOgrMapToPixelSimplifier::~QgsOgrMapToPixelSimplifier()
{
if ( mPointBufferPtr )
{
OGRFree( mPointBufferPtr );
mPointBufferPtr = NULL;
}
}

//! Returns a point buffer of the specified size
QgsPoint* QgsOgrMapToPixelSimplifier::mallocPoints( int numPoints )
{
if ( mPointBufferPtr && mPointBufferCount < numPoints )
{
OGRFree( mPointBufferPtr );
mPointBufferPtr = NULL;
}
if ( !mPointBufferPtr )
{
mPointBufferCount = numPoints;
mPointBufferPtr = ( QgsPoint* )OGRMalloc( mPointBufferCount * sizeof( QgsPoint ) );
}
return mPointBufferPtr;
}

//! Returns a point buffer of the specified envelope
QgsPoint* QgsOgrMapToPixelSimplifier::getEnvelopePoints( const QgsRectangle& envelope, int& numPoints, bool isaLinearRing )
{
QgsPoint* points = NULL;

double x1 = envelope.xMinimum();
double y1 = envelope.yMinimum();
double x2 = envelope.xMaximum();
double y2 = envelope.yMaximum();

if ( isaLinearRing )
{
numPoints = 5;
points = mallocPoints( numPoints );
points[0].set( x1, y1 );
points[1].set( x2, y1 );
points[2].set( x2, y2 );
points[3].set( x1, y2 );
points[4].set( x1, y1 );
}
else
{
numPoints = 2;
points = mallocPoints( numPoints );
points[0].set( x1, y1 );
points[1].set( x2, y2 );
}
return points;
}

//////////////////////////////////////////////////////////////////////////////////////////////
// Helper simplification methods

//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( QGis::GeometryType geometryType, const QgsRectangle& envelope, double *xptr, double *yptr, int pointCount, int& pointSimplifiedCount )
bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( QGis::GeometryType geometryType, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount )
{
Q_UNUSED( envelope )
bool canbeGeneralizable = ( mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyGeometry );

pointSimplifiedCount = pointCount;
Expand All @@ -84,20 +139,20 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( QGis::GeometryType geometr
double map2pixelTol = mMapToPixelTol * mMapToPixelTol; //-> Use mappixelTol for 'LengthSquare' calculations.
double x, y, lastX = 0, lastY = 0;

double *xsourcePtr = xptr;
double *ysourcePtr = yptr;
double *xtargetPtr = xptr;
double *ytargetPtr = yptr;
char* xsourcePtr = ( char* )xptr;
char* ysourcePtr = ( char* )yptr;
char* xtargetPtr = ( char* )xptr;
char* ytargetPtr = ( char* )yptr;

for ( int i = 0, numPoints = geometryType == QGis::Polygon ? pointCount - 1 : pointCount; i < numPoints; ++i )
{
memcpy( &x, xsourcePtr++, sizeof( double ) );
memcpy( &y, ysourcePtr++, sizeof( double ) );
memcpy( &x, xsourcePtr, sizeof( double ) ); xsourcePtr += xStride;
memcpy( &y, ysourcePtr, sizeof( double ) ); ysourcePtr += yStride;

if ( i == 0 || !canbeGeneralizable || QgsMapToPixelSimplifier::calculateLengthSquared2D( x, y, lastX, lastY ) > map2pixelTol || ( geometryType == QGis::Line && ( i == 1 || i >= numPoints - 2 ) ) )
{
memcpy( xtargetPtr++, &x, sizeof( double ) ); lastX = x;
memcpy( ytargetPtr++, &y, sizeof( double ) ); lastY = y;
memcpy( xtargetPtr, &x, sizeof( double ) ); lastX = x; xtargetPtr += xStride;
memcpy( ytargetPtr, &y, sizeof( double ) ); lastY = y; ytargetPtr += yStride;
pointSimplifiedCount++;
}
}
Expand All @@ -107,7 +162,6 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( QGis::GeometryType geometr
memcpy( ytargetPtr, yptr, sizeof( double ) );
pointSimplifiedCount++;
}

return pointSimplifiedCount != pointCount;
}

Expand All @@ -120,7 +174,8 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometryH geometry, boo
if ( wkbGeometryType == wkbLineString )
{
int numPoints = OGR_G_GetPointCount( geometry );
if (( isaLinearRing && numPoints <= 5 ) || ( !isaLinearRing && numPoints <= 4 ) )

if (( isaLinearRing && numPoints <= 5 ) || ( !isaLinearRing && numPoints <= 4 ) )
return false;

OGREnvelope env;
Expand All @@ -130,25 +185,9 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometryH geometry, boo
// Can replace the geometry by its BBOX ?
if (( mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyEnvelope ) && canbeGeneralizedByMapBoundingBox( envelope ) )
{
double x1 = envelope.xMinimum();
double y1 = envelope.yMinimum();
double x2 = envelope.xMaximum();
double y2 = envelope.yMaximum();

if ( isaLinearRing )
{
OGR_G_SetPoint( geometry, 0, x1, y1, 0.0 );
OGR_G_SetPoint( geometry, 1, x2, y1, 0.0 );
OGR_G_SetPoint( geometry, 2, x2, y2, 0.0 );
OGR_G_SetPoint( geometry, 3, x1, y2, 0.0 );
OGR_G_SetPoint( geometry, 4, x1, y1, 0.0 );
}
else
{
OGR_G_SetPoint( geometry, 0, x1, y1, 0.0 );
OGR_G_SetPoint( geometry, 1, x2, y2, 0.0 );
}
QgsPoint* points = getEnvelopePoints( envelope, numPoints, isaLinearRing );

setGeometryPoints( geometry, points, numPoints );
OGR_G_FlattenTo2D( geometry );

return true;
Expand All @@ -158,22 +197,19 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometryH geometry, boo
QGis::GeometryType geometryType = isaLinearRing ? QGis::Polygon : QGis::Line;
int numSimplifiedPoints = 0;

QVector<double> x( numPoints ), y( numPoints );
for ( int i = 0; i < numPoints; i++ )
{
double z;
OGR_G_GetPoint( geometry, i, &x[i], &y[i], &z );
}
QgsPoint* points = mallocPoints( numPoints );
double* xptr = ( double* )points;
double* yptr = xptr + 1;
OGR_G_GetPoints( geometry, xptr, 16, yptr, 16, NULL, 0 );

if ( simplifyOgrGeometry( geometryType, envelope, x.data(), y.data(), numPoints, numSimplifiedPoints ) )
if ( simplifyOgrGeometry( geometryType, xptr, 16, yptr, 16, numPoints, numSimplifiedPoints ) )
{
for ( int i = 0; i < numSimplifiedPoints; i++ )
{
OGR_G_SetPoint( geometry, i, x[i], y[i], 0.0 );
}
if (( isaLinearRing && numSimplifiedPoints <= 4 ) || ( !isaLinearRing && numSimplifiedPoints <= 1 ) )
points = getEnvelopePoints( envelope, numSimplifiedPoints, isaLinearRing );

setGeometryPoints( geometry, points, numSimplifiedPoints );
OGR_G_FlattenTo2D( geometry );
}

return numSimplifiedPoints != numPoints;
}
}
Expand All @@ -195,18 +231,29 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometryH geometry, boo
{
bool result = false;

for ( int i = 1, numGeometries = OGR_G_GetGeometryCount( geometry ); i < numGeometries; ++i )
for ( int i = 0, numGeometries = OGR_G_GetGeometryCount( geometry ); i < numGeometries; ++i )
{
result |= simplifyOgrGeometry( OGR_G_GetGeometryRef( geometry, i ), wkbGeometryType == wkbMultiPolygon );
}

if ( result )
OGR_G_FlattenTo2D( geometry );

return result;
}

return false;
}

//! Load a point array to the specified LineString geometry
void QgsOgrMapToPixelSimplifier::setGeometryPoints( OGRGeometryH geometry, QgsPoint* points, int numPoints )
{
double* xptr = ( double* )points;
double* yptr = xptr + 1;

OGR_G_SetPoints( geometry, numPoints, xptr, 16, yptr, 16, NULL, 0 );
}

//////////////////////////////////////////////////////////////////////////////////////////////

//! Simplifies the specified geometry
Expand All @@ -221,3 +268,5 @@ bool QgsOgrMapToPixelSimplifier::simplifyGeometry( OGRGeometryH geometry )

return false;
}

#endif
19 changes: 18 additions & 1 deletion src/providers/ogr/qgsogrgeometrysimplifier.h
Expand Up @@ -18,6 +18,8 @@
#define QGSOGRGEOMETRYSIMPLIFIER_H

#include "qgsmaptopixelgeometrysimplifier.h"
#include "qgspoint.h"

#include <ogr_api.h>

/**
Expand Down Expand Up @@ -50,6 +52,7 @@ class QgsOgrTopologyPreservingSimplifier : public QgsOgrAbstractGeometrySimplifi
};
#endif

#if defined(GDAL_VERSION_NUM) && defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0)
/**
* OGR implementation of GeometrySimplifier using the "MapToPixel" algorithm
*
Expand All @@ -63,14 +66,28 @@ class QgsOgrMapToPixelSimplifier : public QgsOgrAbstractGeometrySimplifier, QgsM
virtual ~QgsOgrMapToPixelSimplifier();

private:
//! Point memory buffer for optimize the simplification process
QgsPoint* mPointBufferPtr;
//! Current Point memory buffer size
int mPointBufferCount;

//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
bool simplifyOgrGeometry( QGis::GeometryType geometryType, const QgsRectangle& envelope, double *xptr, double *yptr, int pointCount, int &pointSimplifiedCount );
bool simplifyOgrGeometry( QGis::GeometryType geometryType, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount );
//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
bool simplifyOgrGeometry( OGRGeometryH geometry, bool isaLinearRing );

//! Returns a point buffer of the specified size
QgsPoint* mallocPoints( int numPoints );
//! Returns a point buffer of the specified envelope
QgsPoint* getEnvelopePoints( const QgsRectangle& envelope, int& numPoints, bool isaLinearRing );

//! Load a point array to the specified LineString geometry
static void setGeometryPoints( OGRGeometryH geometry, QgsPoint* points, int numPoints );

public:
//! Simplifies the specified geometry
virtual bool simplifyGeometry( OGRGeometryH geometry );
};
#endif

#endif // QGSOGRGEOMETRYSIMPLIFIER_H
7 changes: 6 additions & 1 deletion src/providers/ogr/qgsogrprovider.cpp
Expand Up @@ -1495,7 +1495,12 @@ int QgsOgrProvider::capabilities() const
}

// supports geometry simplification on provider side
ability |= ( QgsVectorDataProvider::SimplifyGeometries | QgsVectorDataProvider::SimplifyGeometriesWithTopologicalValidation );
#if defined(GDAL_VERSION_NUM) && defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0)
ability |= QgsVectorDataProvider::SimplifyGeometries;
#endif
#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1900
ability |= QgsVectorDataProvider::SimplifyGeometriesWithTopologicalValidation;
#endif
}

return ability;
Expand Down

0 comments on commit 12a463d

Please sign in to comment.