Skip to content

Commit cb292c1

Browse files
committedNov 2, 2017
Greatly simplify and optimise interpolation code, correct handling of
Z/M dimensioned geometries
1 parent b369ef8 commit cb292c1

File tree

2 files changed

+49
-233
lines changed

2 files changed

+49
-233
lines changed
 

‎src/analysis/interpolation/qgsinterpolator.cpp

Lines changed: 13 additions & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ QgsInterpolator::Result QgsInterpolator::cacheBaseData( QgsFeedback *feedback )
3232
{
3333
if ( mLayerData.empty() )
3434
{
35-
return 0;
35+
return Success;
3636
}
3737

3838
//reserve initial memory for 100000 vertices
@@ -49,7 +49,7 @@ QgsInterpolator::Result QgsInterpolator::cacheBaseData( QgsFeedback *feedback )
4949
QgsFeatureSource *source = layer.source;
5050
if ( !source )
5151
{
52-
return 2;
52+
return InvalidSource;
5353
}
5454

5555
QgsAttributeList attList;
@@ -95,237 +95,26 @@ QgsInterpolator::Result QgsInterpolator::cacheBaseData( QgsFeedback *feedback )
9595
layerCount++;
9696
}
9797

98-
return 0;
98+
return Success;
9999
}
100100

101-
int QgsInterpolator::addVerticesToCache( const QgsGeometry &geom, bool zCoord, double attributeValue )
101+
bool QgsInterpolator::addVerticesToCache( const QgsGeometry &geom, bool zCoord, double attributeValue )
102102
{
103-
if ( geom.isNull() )
104-
return 1;
103+
if ( !geom || geom.isEmpty() )
104+
return true; // nothing to do
105105

106-
bool hasZValue = false;
107-
QByteArray wkb( geom.exportToWkb() );
108-
QgsConstWkbPtr currentWkbPtr( wkb );
109-
currentWkbPtr.readHeader();
110-
vertexData vertex; //the current vertex
111-
112-
QgsWkbTypes::Type wkbType = geom.wkbType();
113-
switch ( wkbType )
106+
bool hasZ = geom.constGet()->is3D();
107+
for ( auto point = geom.vertices_begin(); point != geom.vertices_end(); ++point )
114108
{
115-
case QgsWkbTypes::Point25D:
116-
hasZValue = true;
117-
//intentional fall-through
118-
FALLTHROUGH;
119-
case QgsWkbTypes::Point:
120-
{
121-
currentWkbPtr >> vertex.x >> vertex.y;
122-
if ( zCoord && hasZValue )
123-
{
124-
currentWkbPtr >> vertex.z;
125-
}
126-
else
127-
{
128-
vertex.z = attributeValue;
129-
}
130-
mCachedBaseData.push_back( vertex );
131-
break;
132-
}
133-
case QgsWkbTypes::LineString25D:
134-
hasZValue = true;
135-
//intentional fall-through
136-
FALLTHROUGH;
137-
case QgsWkbTypes::LineString:
138-
{
139-
int nPoints;
140-
currentWkbPtr >> nPoints;
141-
for ( int index = 0; index < nPoints; ++index )
142-
{
143-
currentWkbPtr >> vertex.x >> vertex.y;
144-
if ( zCoord && hasZValue ) //skip z-coordinate for 25D geometries
145-
{
146-
currentWkbPtr >> vertex.z;
147-
}
148-
else
149-
{
150-
vertex.z = attributeValue;
151-
}
152-
mCachedBaseData.push_back( vertex );
153-
}
154-
break;
155-
}
156-
#if 0
157-
case QgsWkbTypes::Polygon25D:
158-
hasZValue = true;
159-
//intentional fall-through
160-
case QgsWkbTypes::Polygon:
161-
{
162-
int nRings;
163-
wkbPtr >> nRings;
164-
for ( int index = 0; index < nRings; ++index )
165-
{
166-
int nPoints;
167-
wkbPtr >> nPoints;
168-
for ( int index2 = 0; index2 < *npoints; ++index2 )
169-
{
170-
double x, y;
171-
wkbPtr >> x >> y;
172-
if ( point.sqrDist( x, y ) < actdist )
173-
{
174-
actdist = point.sqrDist( x, y );
175-
vertexnr = vertexcounter;
176-
//assign the rubber band indices
177-
if ( index2 == 0 )
178-
{
179-
beforeVertex = vertexcounter + ( *npoints - 2 );
180-
afterVertex = vertexcounter + 1;
181-
}
182-
else if ( index2 == ( *npoints - 1 ) )
183-
{
184-
beforeVertex = vertexcounter - 1;
185-
afterVertex = vertexcounter - ( *npoints - 2 );
186-
}
187-
else
188-
{
189-
beforeVertex = vertexcounter - 1;
190-
afterVertex = vertexcounter + 1;
191-
}
192-
}
193-
if ( hasZValue ) //skip z-coordinate for 25D geometries
194-
{
195-
wkbPtr += sizeof( double );
196-
}
197-
++vertexcounter;
198-
}
199-
}
200-
break;
201-
}
202-
case QgsWkbTypes::MultiPoint25D:
203-
hasZValue = true;
204-
//intentional fall-through
205-
case QgsWkbTypes::MultiPoint:
206-
{
207-
int nPoints;
208-
wkbPtr >> nPoints;
209-
for ( int index = 0; index < nPoints; ++index )
210-
{
211-
wkbPtr += 1 + sizeof( int ); //skip endian and point type
212-
213-
double x, y;
214-
wkbPtr >> x >> y;
215-
if ( point.sqrDist( x, y ) < actdist )
216-
{
217-
actdist = point.sqrDist( x, y );
218-
vertexnr = index;
219-
}
220-
if ( hasZValue ) //skip z-coordinate for 25D geometries
221-
{
222-
wkbPtr += sizeof( double );
223-
}
224-
}
225-
break;
226-
}
227-
case QgsWkbTypes::MultiLineString25D:
228-
hasZValue = true;
229-
//intentional fall-through
230-
case QgsWkbTypes::MultiLineString:
109+
if ( hasZ && zCoord )
231110
{
232-
int nLines;
233-
wkbPtr >> nLines;
234-
for ( int index = 0; index < nLines; ++index )
235-
{
236-
int nPoints;
237-
wkbPtr >> nPoints;
238-
for ( int index2 = 0; index2 < nPoints; ++index2 )
239-
{
240-
double x, y;
241-
wkbPtr >> x >> y;
242-
if ( point.sqrDist( x, y ) < actdist )
243-
{
244-
actdist = point.sqrDist( x, y );
245-
vertexnr = vertexcounter;
246-
247-
if ( index2 == 0 )//assign the rubber band indices
248-
{
249-
beforeVertex = -1;
250-
}
251-
else
252-
{
253-
beforeVertex = vertexnr - 1;
254-
}
255-
if ( index2 == nPoints - 1 )
256-
{
257-
afterVertex = -1;
258-
}
259-
else
260-
{
261-
afterVertex = vertexnr + 1;
262-
}
263-
}
264-
if ( hasZValue ) //skip z-coordinate for 25D geometries
265-
{
266-
wkbPtr += sizeof( double );
267-
}
268-
++vertexcounter;
269-
}
270-
}
271-
break;
111+
mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), ( *point ).z() ) );
272112
}
273-
case QgsWkbTypes::MultiPolygon25D:
274-
hasZValue = true;
275-
//intentional fall-through
276-
case QgsWkbTypes::MultiPolygon:
113+
else
277114
{
278-
int nPolys;
279-
wkbPtr >> nPolys;
280-
for ( int index = 0; index < nPolys; ++index )
281-
{
282-
wkbPtr += 1 + sizeof( int ); //skip endian and polygon type
283-
int nRings;
284-
wkbPtr >> nRings;
285-
for ( int index2 = 0; index2 < nRings; ++index2 )
286-
{
287-
int nPoints;
288-
wkbPtr >> nPoints;
289-
for ( int index3 = 0; index3 < nPoints; ++index3 )
290-
{
291-
double x, y;
292-
wkbPtr >> x >> y;
293-
if ( point.sqrDist( x, y ) < actdist )
294-
{
295-
actdist = point.sqrDist( x, y );
296-
vertexnr = vertexcounter;
297-
298-
//assign the rubber band indices
299-
if ( index3 == 0 )
300-
{
301-
beforeVertex = vertexcounter + ( nPoints - 2 );
302-
afterVertex = vertexcounter + 1;
303-
}
304-
else if ( index3 == ( *npoints - 1 ) )
305-
{
306-
beforeVertex = vertexcounter - 1;
307-
afterVertex = vertexcounter - ( nPoints - 2 );
308-
}
309-
else
310-
{
311-
beforeVertex = vertexcounter - 1;
312-
afterVertex = vertexcounter + 1;
313-
}
314-
}
315-
if ( hasZValue ) //skip z-coordinate for 25D geometries
316-
{
317-
wkbPtr += sizeof( double );
318-
}
319-
++vertexcounter;
320-
}
321-
}
322-
}
323-
break;
115+
mCachedBaseData.push_back( QgsInterpolatorVertexData( ( *point ).x(), ( *point ).y(), attributeValue ) );
324116
}
325-
#endif //0
326-
default:
327-
break;
328117
}
329118
mDataIsCached = true;
330-
return 0;
119+
return true;
331120
}

‎src/analysis/interpolation/qgsinterpolator.h

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,26 @@ class QgsFeedback;
3232
*/
3333
struct ANALYSIS_EXPORT QgsInterpolatorVertexData
3434
{
35-
double x;
36-
double y;
37-
double z;
35+
36+
/**
37+
* Constructor for QgsInterpolatorVertexData with the specified
38+
* \a x, \a y, and \a z coordinate.
39+
*/
40+
QgsInterpolatorVertexData( double x, double y, double z )
41+
: x( x )
42+
, y( y )
43+
, z( z )
44+
{}
45+
46+
//! Constructor for QgsInterpolatorVertexData
47+
QgsInterpolatorVertexData() = default;
48+
49+
//! X-coordinate
50+
double x = 0.0;
51+
//! Y-coordinate
52+
double y = 0.0;
53+
//! Z-coordinate
54+
double z = 0.0;
3855
};
3956

4057
/**
@@ -55,7 +72,16 @@ class ANALYSIS_EXPORT QgsInterpolator
5572
SourceBreakLines, //!< Break lines
5673
};
5774

58-
//! A layer together with the information about interpolation attribute / z-coordinate interpolation and the type (point, structure line, breakline)
75+
//! Result of an interpolation operation
76+
enum Result
77+
{
78+
Success = 0, //!< Operation was successful
79+
Canceled, //!< Operation was manually canceled
80+
InvalidSource, //!< Operation failed due to invalid source
81+
FeatureGeometryError, //!< Operation failed due to invalid feature geometry
82+
};
83+
84+
//! A source together with the information about interpolation attribute / z-coordinate interpolation and the type (point, structure line, breakline)
5985
struct LayerData
6086
{
6187
//! Feature source
@@ -111,11 +137,12 @@ class ANALYSIS_EXPORT QgsInterpolator
111137

112138
/**
113139
* Helper method that adds the vertices of a geometry to the mCachedBaseData
114-
\param geom the geometry
115-
\param zCoord true if the z-coordinate of the geometry is to be interpolated
116-
\param attributeValue the attribute value for interpolation (if not interpolated from z-coordinate)
117-
\returns 0 in case of success*/
118-
int addVerticesToCache( const QgsGeometry &geom, bool zCoord, double attributeValue );
140+
* \param geom the geometry
141+
* \param zCoord true if the z-coordinate of the geometry is to be interpolated
142+
* \param attributeValue the attribute value for interpolation (if not interpolated from z-coordinate)
143+
*\returns 0 in case of success
144+
*/
145+
bool addVerticesToCache( const QgsGeometry &geom, bool zCoord, double attributeValue );
119146
};
120147

121148
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.