Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug #9360-revival: fix whole layer not rendered (when simplify geometry activated) #1087

Merged
merged 6 commits into from
Jan 22, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions src/providers/ogr/qgsogrfeatureiterator.cpp
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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