Skip to content

Commit 2e81934

Browse files
committed
#9360R: fix bad ogr simplification
1 parent 06b1fbc commit 2e81934

File tree

2 files changed

+87
-50
lines changed

2 files changed

+87
-50
lines changed

src/providers/ogr/qgsogrgeometrysimplifier.cpp

Lines changed: 76 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,41 @@ bool QgsOgrTopologyPreservingSimplifier::simplifyGeometry( OGRGeometryH geometry
6262
QgsOgrMapToPixelSimplifier::QgsOgrMapToPixelSimplifier( int simplifyFlags, double map2pixelTol )
6363
: QgsMapToPixelSimplifier( simplifyFlags, map2pixelTol )
6464
{
65+
mPointBufferCount = 64;
66+
mPointBufferPtr = ( OGRRawPoint* )OGRMalloc( mPointBufferCount * sizeof( OGRRawPoint ) );
6567
}
6668

6769
QgsOgrMapToPixelSimplifier::~QgsOgrMapToPixelSimplifier()
6870
{
71+
if ( mPointBufferPtr )
72+
{
73+
OGRFree( mPointBufferPtr );
74+
mPointBufferPtr = NULL;
75+
}
76+
}
77+
78+
//! Returns a point buffer of the specified size
79+
OGRRawPoint* QgsOgrMapToPixelSimplifier::mallocPoints( int numPoints )
80+
{
81+
if ( mPointBufferPtr && mPointBufferCount < numPoints )
82+
{
83+
OGRFree( mPointBufferPtr );
84+
mPointBufferPtr = NULL;
85+
}
86+
if ( mPointBufferPtr == NULL )
87+
{
88+
mPointBufferCount = numPoints;
89+
mPointBufferPtr = ( OGRRawPoint* )OGRMalloc( mPointBufferCount * sizeof( OGRRawPoint ) );
90+
}
91+
return mPointBufferPtr;
6992
}
7093

7194
//////////////////////////////////////////////////////////////////////////////////////////////
7295
// Helper simplification methods
7396

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

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

87-
double *xsourcePtr = xptr;
88-
double *ysourcePtr = yptr;
89-
double *xtargetPtr = xptr;
90-
double *ytargetPtr = yptr;
109+
char* xsourcePtr = ( char* )xptr;
110+
char* ysourcePtr = ( char* )yptr;
111+
char* xtargetPtr = ( char* )xptr;
112+
char* ytargetPtr = ( char* )yptr;
91113

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

97119
if ( i == 0 || !canbeGeneralizable || QgsMapToPixelSimplifier::calculateLengthSquared2D( x, y, lastX, lastY ) > map2pixelTol || ( geometryType == QGis::Line && ( i == 1 || i >= numPoints - 2 ) ) )
98120
{
99-
memcpy( xtargetPtr++, &x, sizeof( double ) ); lastX = x;
100-
memcpy( ytargetPtr++, &y, sizeof( double ) ); lastY = y;
121+
memcpy( xtargetPtr, &x, sizeof( double ) ); lastX = x; xtargetPtr += xStride;
122+
memcpy( ytargetPtr, &y, sizeof( double ) ); lastY = y; ytargetPtr += yStride;
101123
pointSimplifiedCount++;
102124
}
103125
}
@@ -107,49 +129,57 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( QGis::GeometryType geometr
107129
memcpy( ytargetPtr, yptr, sizeof( double ) );
108130
pointSimplifiedCount++;
109131
}
110-
111132
return pointSimplifiedCount != pointCount;
112133
}
113134

114135
//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
115-
bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometryH geometry, bool isaLinearRing )
136+
bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometry* geometry, bool isaLinearRing )
116137
{
117-
OGRwkbGeometryType wkbGeometryType = wkbFlatten( OGR_G_GetGeometryType( geometry ) );
138+
OGRwkbGeometryType wkbGeometryType = wkbFlatten( geometry->getGeometryType() );
118139

119140
// Simplify the geometry rewriting temporally its WKB-stream for saving calloc's.
120141
if ( wkbGeometryType == wkbLineString )
121142
{
122-
int numPoints = OGR_G_GetPointCount( geometry );
123-
if (( isaLinearRing && numPoints <= 5 ) || ( !isaLinearRing && numPoints <= 4 ) )
143+
OGRLineString* lineString = ( OGRLineString* )geometry;
144+
145+
int numPoints = lineString->getNumPoints();
146+
if (( isaLinearRing && numPoints <= 5 ) || ( !isaLinearRing && numPoints <= 4 ) )
124147
return false;
125148

126149
OGREnvelope env;
127-
OGR_G_GetEnvelope( geometry, &env );
150+
geometry->getEnvelope( &env );
128151
QgsRectangle envelope( env.MinX, env.MinY, env.MaxX, env.MaxY );
129152

130153
// Can replace the geometry by its BBOX ?
131154
if (( mSimplifyFlags & QgsMapToPixelSimplifier::SimplifyEnvelope ) && canbeGeneralizedByMapBoundingBox( envelope ) )
132155
{
156+
OGRRawPoint* points = NULL;
157+
int numPoints = 0;
158+
133159
double x1 = envelope.xMinimum();
134160
double y1 = envelope.yMinimum();
135161
double x2 = envelope.xMaximum();
136162
double y2 = envelope.yMaximum();
137163

138164
if ( isaLinearRing )
139165
{
140-
OGR_G_SetPoint( geometry, 0, x1, y1, 0.0 );
141-
OGR_G_SetPoint( geometry, 1, x2, y1, 0.0 );
142-
OGR_G_SetPoint( geometry, 2, x2, y2, 0.0 );
143-
OGR_G_SetPoint( geometry, 3, x1, y2, 0.0 );
144-
OGR_G_SetPoint( geometry, 4, x1, y1, 0.0 );
166+
numPoints = 5;
167+
points = mallocPoints( numPoints );
168+
points[0].x = x1; points[0].y = y1;
169+
points[1].x = x2; points[1].y = y1;
170+
points[2].x = x2; points[2].y = y2;
171+
points[3].x = x1; points[3].y = y2;
172+
points[4].x = x1; points[4].y = y1;
145173
}
146174
else
147175
{
148-
OGR_G_SetPoint( geometry, 0, x1, y1, 0.0 );
149-
OGR_G_SetPoint( geometry, 1, x2, y2, 0.0 );
176+
numPoints = 2;
177+
points = mallocPoints( numPoints );
178+
points[0].x = x1; points[0].y = y1;
179+
points[1].x = x2; points[1].y = y2;
150180
}
151-
152-
OGR_G_FlattenTo2D( geometry );
181+
lineString->setPoints( numPoints, points );
182+
lineString->flattenTo2D();
153183

154184
return true;
155185
}
@@ -158,49 +188,47 @@ bool QgsOgrMapToPixelSimplifier::simplifyOgrGeometry( OGRGeometryH geometry, boo
158188
QGis::GeometryType geometryType = isaLinearRing ? QGis::Polygon : QGis::Line;
159189
int numSimplifiedPoints = 0;
160190

161-
QVector<double> x( numPoints ), y( numPoints );
162-
for ( int i = 0; i < numPoints; i++ )
163-
{
164-
double z;
165-
OGR_G_GetPoint( geometry, i, &x[i], &y[i], &z );
166-
}
191+
OGRRawPoint* points = mallocPoints( numPoints );
192+
double* xptr = ( double* )points;
193+
double* yptr = xptr + 1;
194+
lineString->getPoints( points );
167195

168-
if ( simplifyOgrGeometry( geometryType, envelope, x.data(), y.data(), numPoints, numSimplifiedPoints ) )
196+
if ( simplifyOgrGeometry( geometryType, xptr, 16, yptr, 16, numPoints, numSimplifiedPoints ) )
169197
{
170-
for ( int i = 0; i < numSimplifiedPoints; i++ )
171-
{
172-
OGR_G_SetPoint( geometry, i, x[i], y[i], 0.0 );
173-
}
174-
OGR_G_FlattenTo2D( geometry );
198+
lineString->setPoints( numSimplifiedPoints, points );
199+
lineString->flattenTo2D();
175200
}
176-
177201
return numSimplifiedPoints != numPoints;
178202
}
179203
}
180204
else if ( wkbGeometryType == wkbPolygon )
181205
{
182-
bool result = simplifyOgrGeometry( OGR_G_GetGeometryRef( geometry, 0 ), true );
206+
OGRPolygon* polygon = ( OGRPolygon* )geometry;
207+
bool result = simplifyOgrGeometry( polygon->getExteriorRing(), true );
183208

184-
for ( int i = 1, numInteriorRings = OGR_G_GetGeometryCount( geometry ); i < numInteriorRings; ++i )
209+
for ( int i = 0, numInteriorRings = polygon->getNumInteriorRings(); i < numInteriorRings; ++i )
185210
{
186-
result |= simplifyOgrGeometry( OGR_G_GetGeometryRef( geometry, i ), true );
211+
result |= simplifyOgrGeometry( polygon->getInteriorRing( i ), true );
187212
}
188213

189-
if ( result )
190-
OGR_G_FlattenTo2D( geometry );
214+
if ( result )
215+
polygon->flattenTo2D();
191216

192217
return result;
193218
}
194219
else if ( wkbGeometryType == wkbMultiLineString || wkbGeometryType == wkbMultiPolygon )
195220
{
221+
OGRGeometryCollection* collection = ( OGRGeometryCollection* )geometry;
196222
bool result = false;
197223

198-
for ( int i = 1, numGeometries = OGR_G_GetGeometryCount( geometry ); i < numGeometries; ++i )
224+
for ( int i = 0, numGeometries = collection->getNumGeometries(); i < numGeometries; ++i )
199225
{
200-
result |= simplifyOgrGeometry( OGR_G_GetGeometryRef( geometry, i ), wkbGeometryType == wkbMultiPolygon );
226+
result |= simplifyOgrGeometry( collection->getGeometryRef( i ), wkbGeometryType == wkbMultiPolygon );
201227
}
202-
if ( result )
203-
OGR_G_FlattenTo2D( geometry );
228+
229+
if ( result )
230+
collection->flattenTo2D();
231+
204232
return result;
205233
}
206234

@@ -216,7 +244,7 @@ bool QgsOgrMapToPixelSimplifier::simplifyGeometry( OGRGeometryH geometry )
216244

217245
if ( wkbGeometryType == wkbLineString || wkbGeometryType == wkbPolygon )
218246
{
219-
return simplifyOgrGeometry( geometry, wkbGeometryType == wkbPolygon );
247+
return simplifyOgrGeometry( (OGRGeometry*) geometry, wkbGeometryType == wkbPolygon );
220248
}
221249

222250
return false;

src/providers/ogr/qgsogrgeometrysimplifier.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "qgsmaptopixelgeometrysimplifier.h"
2121
#include <ogr_api.h>
22+
#include <ogr_geometry.h>
2223

2324
/**
2425
* Abstract base class for simplify OGR-geometries using a specific algorithm
@@ -63,10 +64,18 @@ class QgsOgrMapToPixelSimplifier : public QgsOgrAbstractGeometrySimplifier, QgsM
6364
virtual ~QgsOgrMapToPixelSimplifier();
6465

6566
private:
67+
//! Point memory buffer for optimize the simplification process
68+
OGRRawPoint* mPointBufferPtr;
69+
//! Current Point memory buffer size
70+
int mPointBufferCount;
71+
6672
//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
67-
bool simplifyOgrGeometry( QGis::GeometryType geometryType, const QgsRectangle& envelope, double *xptr, double *yptr, int pointCount, int &pointSimplifiedCount );
73+
bool simplifyOgrGeometry( QGis::GeometryType geometryType, double* xptr, int xStride, double* yptr, int yStride, int pointCount, int& pointSimplifiedCount );
6874
//! Simplifies the OGR-geometry (Removing duplicated points) when is applied the specified map2pixel context
69-
bool simplifyOgrGeometry( OGRGeometryH geometry, bool isaLinearRing );
75+
bool simplifyOgrGeometry( OGRGeometry* geometry, bool isaLinearRing );
76+
77+
//! Returns a point buffer of the specified size
78+
OGRRawPoint* mallocPoints( int numPoints );
7079

7180
public:
7281
//! Simplifies the specified geometry

0 commit comments

Comments
 (0)