Skip to content

Commit f79dfa1

Browse files
committed
#9360R: enable ogr simplification for GDAL-OGR >= 1.11
1 parent 0c99423 commit f79dfa1

4 files changed

+77
-78
lines changed

src/providers/ogr/qgsogrfeatureiterator.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ bool QgsOgrFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simp
111111
QgsSimplifyMethod::MethodType methodType = simplifyMethod.methodType();
112112
Q_UNUSED( methodType);
113113

114-
#if defined(HAVE_OGR_GEOMETRY_CLASS)
114+
#if defined(GDAL_VERSION_NUM) && defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0)
115115
if ( methodType == QgsSimplifyMethod::OptimizeForRendering )
116116
{
117117
int simplifyFlags = QgsMapToPixelSimplifier::SimplifyGeometry | QgsMapToPixelSimplifier::SimplifyEnvelope;
@@ -134,7 +134,7 @@ bool QgsOgrFeatureIterator::prepareSimplification( const QgsSimplifyMethod& simp
134134

135135
bool QgsOgrFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
136136
{
137-
#if defined(HAVE_OGR_GEOMETRY_CLASS)
137+
#if defined(GDAL_VERSION_NUM) && defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0)
138138
if ( methodType == QgsSimplifyMethod::OptimizeForRendering )
139139
{
140140
return true;

src/providers/ogr/qgsogrgeometrysimplifier.cpp

+63-48
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ QgsOgrAbstractGeometrySimplifier::~QgsOgrAbstractGeometrySimplifier()
2525
/***************************************************************************/
2626

2727
#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1900
28+
2829
QgsOgrTopologyPreservingSimplifier::QgsOgrTopologyPreservingSimplifier( double tolerance )
2930
: QgsTopologyPreservingSimplifier( tolerance )
3031
{
@@ -59,10 +60,7 @@ bool QgsOgrTopologyPreservingSimplifier::simplifyGeometry( OGRGeometryH geometry
5960

6061
/***************************************************************************/
6162

62-
#if defined(HAVE_OGR_GEOMETRY_CLASS)
63-
64-
// Use OgrGeometry class to speed up simplification on provider side
65-
#include <ogr_geometry.h>
63+
#if defined(GDAL_VERSION_NUM) && defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0)
6664

6765
QgsOgrMapToPixelSimplifier::QgsOgrMapToPixelSimplifier( int simplifyFlags, double map2pixelTol )
6866
: QgsMapToPixelSimplifier( simplifyFlags, map2pixelTol )
@@ -81,7 +79,7 @@ QgsOgrMapToPixelSimplifier::~QgsOgrMapToPixelSimplifier()
8179
}
8280

8381
//! Returns a point buffer of the specified size
84-
OGRRawPoint* QgsOgrMapToPixelSimplifier::mallocPoints( int numPoints )
82+
QgsPoint* QgsOgrMapToPixelSimplifier::mallocPoints( int numPoints )
8583
{
8684
if ( mPointBufferPtr && mPointBufferCount < numPoints )
8785
{
@@ -91,11 +89,41 @@ OGRRawPoint* QgsOgrMapToPixelSimplifier::mallocPoints( int numPoints )
9189
if ( !mPointBufferPtr )
9290
{
9391
mPointBufferCount = numPoints;
94-
mPointBufferPtr = ( OGRRawPoint* )OGRMalloc( mPointBufferCount * sizeof( OGRRawPoint ) );
92+
mPointBufferPtr = ( QgsPoint* )OGRMalloc( mPointBufferCount * sizeof( QgsPoint ) );
9593
}
9694
return mPointBufferPtr;
9795
}
9896

97+
//! Returns a point buffer of the specified envelope
98+
QgsPoint* QgsOgrMapToPixelSimplifier::getEnvelopePoints( const QgsRectangle& envelope, int& numPoints, bool isaLinearRing )
99+
{
100+
QgsPoint* points = NULL;
101+
102+
double x1 = envelope.xMinimum();
103+
double y1 = envelope.yMinimum();
104+
double x2 = envelope.xMaximum();
105+
double y2 = envelope.yMaximum();
106+
107+
if ( isaLinearRing )
108+
{
109+
numPoints = 5;
110+
points = mallocPoints( numPoints );
111+
points[0].set( x1, y1 );
112+
points[1].set( x2, y1 );
113+
points[2].set( x2, y2 );
114+
points[3].set( x1, y2 );
115+
points[4].set( x1, y1 );
116+
}
117+
else
118+
{
119+
numPoints = 2;
120+
points = mallocPoints( numPoints );
121+
points[0].set( x1, y1 );
122+
points[1].set( x2, y2 );
123+
}
124+
return points;
125+
}
126+
99127
//////////////////////////////////////////////////////////////////////////////////////////////
100128
// Helper simplification methods
101129

@@ -138,52 +166,29 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( QGis::GeometryType geometr
138166
}
139167

140168
//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
141-
bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometry* geometry, bool isaLinearRing )
169+
bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometryH geometry, bool isaLinearRing )
142170
{
143-
OGRwkbGeometryType wkbGeometryType = wkbFlatten( geometry->getGeometryType() );
171+
OGRwkbGeometryType wkbGeometryType = wkbFlatten( OGR_G_GetGeometryType( geometry ) );
144172

145173
// Simplify the geometry rewriting temporally its WKB-stream for saving calloc's.
146174
if ( wkbGeometryType == wkbLineString )
147175
{
148-
OGRLineString* lineString = ( OGRLineString* )geometry;
176+
int numPoints = OGR_G_GetPointCount( geometry );
149177

150-
int numPoints = lineString->getNumPoints();
151178
if (( isaLinearRing && numPoints <= 5 ) || ( !isaLinearRing && numPoints <= 4 ) )
152179
return false;
153180

154181
OGREnvelope env;
155-
lineString->getEnvelope( &env );
182+
OGR_G_GetEnvelope( geometry, &env );
156183
QgsRectangle envelope( env.MinX, env.MinY, env.MaxX, env.MaxY );
157184

158185
// Can replace the geometry by its BBOX ?
159186
if (( mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyEnvelope ) && canbeGeneralizedByMapBoundingBox( envelope ) )
160187
{
161-
OGRRawPoint* points = NULL;
188+
QgsPoint* points = getEnvelopePoints( envelope, numPoints, isaLinearRing );
162189

163-
double x1 = envelope.xMinimum();
164-
double y1 = envelope.yMinimum();
165-
double x2 = envelope.xMaximum();
166-
double y2 = envelope.yMaximum();
167-
168-
if ( isaLinearRing )
169-
{
170-
numPoints = 5;
171-
points = mallocPoints( numPoints );
172-
points[0].x = x1; points[0].y = y1;
173-
points[1].x = x2; points[1].y = y1;
174-
points[2].x = x2; points[2].y = y2;
175-
points[3].x = x1; points[3].y = y2;
176-
points[4].x = x1; points[4].y = y1;
177-
}
178-
else
179-
{
180-
numPoints = 2;
181-
points = mallocPoints( numPoints );
182-
points[0].x = x1; points[0].y = y1;
183-
points[1].x = x2; points[1].y = y2;
184-
}
185-
lineString->setPoints( numPoints, points );
186-
lineString->flattenTo2D();
190+
setGeometryPoints( geometry, points, numPoints );
191+
OGR_G_FlattenTo2D( geometry );
187192

188193
return true;
189194
}
@@ -192,27 +197,29 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometry* geometry, boo
192197
QGis::GeometryType geometryType = isaLinearRing ? QGis::Polygon : QGis::Line;
193198
int numSimplifiedPoints = 0;
194199

195-
OGRRawPoint* points = mallocPoints( numPoints );
200+
QgsPoint* points = mallocPoints( numPoints );
196201
double* xptr = ( double* )points;
197202
double* yptr = xptr + 1;
198-
lineString->getPoints( points );
203+
OGR_G_GetPoints( geometry, xptr, 16, yptr, 16, NULL, 0 );
199204

200205
if ( simplifyOgrGeometry( geometryType, xptr, 16, yptr, 16, numPoints, numSimplifiedPoints ) )
201206
{
202-
lineString->setPoints( numSimplifiedPoints, points );
203-
lineString->flattenTo2D();
207+
if (( isaLinearRing && numSimplifiedPoints <= 4 ) || ( !isaLinearRing && numSimplifiedPoints <= 1 ) )
208+
points = getEnvelopePoints( envelope, numSimplifiedPoints, isaLinearRing );
209+
210+
setGeometryPoints( geometry, points, numSimplifiedPoints );
211+
OGR_G_FlattenTo2D( geometry );
204212
}
205213
return numSimplifiedPoints != numPoints;
206214
}
207215
}
208216
else if ( wkbGeometryType == wkbPolygon )
209217
{
210-
OGRPolygon* polygon = ( OGRPolygon* )geometry;
211-
bool result = simplifyOgrGeometry( polygon->getExteriorRing(), true );
218+
bool result = simplifyOgrGeometry( OGR_G_GetGeometryRef( geometry, 0 ), true );
212219

213-
for ( int i = 0, numInteriorRings = polygon->getNumInteriorRings(); i < numInteriorRings; ++i )
220+
for ( int i = 1, numInteriorRings = OGR_G_GetGeometryCount( geometry ); i < numInteriorRings; ++i )
214221
{
215-
result |= simplifyOgrGeometry( polygon->getInteriorRing( i ), true );
222+
result |= simplifyOgrGeometry( OGR_G_GetGeometryRef( geometry, i ), true );
216223
}
217224

218225
if ( result )
@@ -222,12 +229,11 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometry* geometry, boo
222229
}
223230
else if ( wkbGeometryType == wkbMultiLineString || wkbGeometryType == wkbMultiPolygon )
224231
{
225-
OGRGeometryCollection* collection = ( OGRGeometryCollection* )geometry;
226232
bool result = false;
227233

228-
for ( int i = 0, numGeometries = collection->getNumGeometries(); i < numGeometries; ++i )
234+
for ( int i = 0, numGeometries = OGR_G_GetGeometryCount( geometry ); i < numGeometries; ++i )
229235
{
230-
result |= simplifyOgrGeometry( collection->getGeometryRef( i ), wkbGeometryType == wkbMultiPolygon );
236+
result |= simplifyOgrGeometry( OGR_G_GetGeometryRef( geometry, i ), wkbGeometryType == wkbMultiPolygon );
231237
}
232238

233239
if ( result )
@@ -239,6 +245,15 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometry* geometry, boo
239245
return false;
240246
}
241247

248+
//! Load a point array to the specified LineString geometry
249+
void QgsOgrMapToPixelSimplifier::setGeometryPoints( OGRGeometryH geometry, QgsPoint* points, int numPoints )
250+
{
251+
double* xptr = ( double* )points;
252+
double* yptr = xptr + 1;
253+
254+
OGR_G_SetPoints( geometry, numPoints, xptr, 16, yptr, 16, NULL, 0 );
255+
}
256+
242257
//////////////////////////////////////////////////////////////////////////////////////////////
243258

244259
//! Simplifies the specified geometry
@@ -248,7 +263,7 @@ bool QgsOgrMapToPixelSimplifier::simplifyGeometry( OGRGeometryH geometry )
248263

249264
if ( wkbGeometryType == wkbLineString || wkbGeometryType == wkbPolygon )
250265
{
251-
return simplifyOgrGeometry( (OGRGeometry*) geometry, wkbGeometryType == wkbPolygon );
266+
return simplifyOgrGeometry( geometry, wkbGeometryType == wkbPolygon );
252267
}
253268

254269
return false;

src/providers/ogr/qgsogrgeometrysimplifier.h

+11-26
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,9 @@
1818
#define QGSOGRGEOMETRYSIMPLIFIER_H
1919

2020
#include "qgsmaptopixelgeometrysimplifier.h"
21-
#include <ogr_api.h>
21+
#include "qgspoint.h"
2222

23-
/* TODO:
24-
* Disable OGR-simplification on provider side because of OGRGeometry class
25-
* (GDAL C++ API) is not available in current QGIS builds.
26-
* This simplification is ~5-10% faster than simplification on QGIS side
27-
* (for very complex polygons up to ~20%).
28-
*
29-
* While GDAL C API has not published the needed method 'OGR_G_SetPoints()'
30-
* to rewrite the geometry of a LineString/LinearRing in one single call,
31-
* we can not enable the OGR-simplification to change the current disabled
32-
* references of OGRGeometry* (GDAL C++ API) to OGRGeometryH (GDAL C API).
33-
*
34-
* Search in 'qgsogrgeometrysimplifier.cpp' : lineString->setPoints(...);
35-
* We can not use 'OGR_G_SetPoint(...)' because of each call reallocs the
36-
* point array of the geometry and it is very-very slow.
37-
*
38-
#if defined(__cplusplus)
39-
#define HAVE_OGR_GEOMETRY_CLASS 1
40-
class OGRGeometry;
41-
class OGRRawPoint;
42-
#endif
43-
*/
23+
#include <ogr_api.h>
4424

4525
/**
4626
* Abstract base class for simplify OGR-geometries using a specific algorithm
@@ -72,7 +52,7 @@ class QgsOgrTopologyPreservingSimplifier : public QgsOgrAbstractGeometrySimplifi
7252
};
7353
#endif
7454

75-
#if defined(HAVE_OGR_GEOMETRY_CLASS)
55+
#if defined(GDAL_VERSION_NUM) && defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0)
7656
/**
7757
* OGR implementation of GeometrySimplifier using the "MapToPixel" algorithm
7858
*
@@ -87,17 +67,22 @@ class QgsOgrMapToPixelSimplifier : public QgsOgrAbstractGeometrySimplifier, QgsM
8767

8868
private:
8969
//! Point memory buffer for optimize the simplification process
90-
OGRRawPoint* mPointBufferPtr;
70+
QgsPoint* mPointBufferPtr;
9171
//! Current Point memory buffer size
9272
int mPointBufferCount;
9373

9474
//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
9575
bool simplifyOgrGeometry( QGis::GeometryType geometryType, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount );
9676
//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
97-
bool simplifyOgrGeometry( OGRGeometry* geometry, bool isaLinearRing );
77+
bool simplifyOgrGeometry( OGRGeometryH geometry, bool isaLinearRing );
9878

9979
//! Returns a point buffer of the specified size
100-
OGRRawPoint* mallocPoints( int numPoints );
80+
QgsPoint* mallocPoints( int numPoints );
81+
//! Returns a point buffer of the specified envelope
82+
QgsPoint* getEnvelopePoints( const QgsRectangle& envelope, int& numPoints, bool isaLinearRing );
83+
84+
//! Load a point array to the specified LineString geometry
85+
static void setGeometryPoints( OGRGeometryH geometry, QgsPoint* points, int numPoints );
10186

10287
public:
10388
//! Simplifies the specified geometry

src/providers/ogr/qgsogrprovider.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ email : sherman at mrcc.com
4545
#include "qgsgeometry.h"
4646
#include "qgscoordinatereferencesystem.h"
4747
#include "qgsvectorlayerimport.h"
48-
#include "qgsogrgeometrysimplifier.h"
4948

5049
static const QString TEXT_PROVIDER_KEY = "ogr";
5150
static const QString TEXT_PROVIDER_DESCRIPTION =
@@ -1496,7 +1495,7 @@ int QgsOgrProvider::capabilities() const
14961495
}
14971496

14981497
// supports geometry simplification on provider side
1499-
#if defined(HAVE_OGR_GEOMETRY_CLASS)
1498+
#if defined(GDAL_VERSION_NUM) && defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(1,11,0)
15001499
ability |= QgsVectorDataProvider::SimplifyGeometries;
15011500
#endif
15021501
#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1900

0 commit comments

Comments
 (0)