Skip to content

Commit 2c8f238

Browse files
committedSep 24, 2018
use spatial index to limit rendering of features
1 parent 9b480af commit 2c8f238

File tree

6 files changed

+121
-47
lines changed

6 files changed

+121
-47
lines changed
 

‎src/core/mesh/qgsmeshlayerrenderer.cpp

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -202,22 +202,42 @@ void QgsMeshLayerRenderer::copyVectorDatasetValues( QgsMeshLayer *layer )
202202

203203
bool QgsMeshLayerRenderer::render()
204204
{
205-
206205
renderScalarDataset();
207-
208-
renderMesh( mRendererSettings.nativeMeshSettings(), mNativeMesh.faces ); // native mesh
209-
renderMesh( mRendererSettings.triangularMeshSettings(), mTriangularMesh.triangles() ); // triangular mesh
210-
206+
renderMesh();
211207
renderVectorDataset();
212-
213208
return true;
214209
}
215210

216-
void QgsMeshLayerRenderer::renderMesh(const QgsMeshRendererMeshSettings& settings , const QVector<QgsMeshFace> &faces)
211+
void QgsMeshLayerRenderer::renderMesh()
217212
{
218-
if ( !settings.isEnabled() )
213+
if ( !mRendererSettings.nativeMeshSettings().isEnabled() &&
214+
!mRendererSettings.triangularMeshSettings().isEnabled() )
219215
return;
220216

217+
// triangular mesh
218+
const QList<int> trianglesInExtent = mTriangularMesh.faceIndexesForRectangle( mContext.extent() );
219+
if ( mRendererSettings.triangularMeshSettings().isEnabled() )
220+
{
221+
renderMesh( mRendererSettings.triangularMeshSettings(),
222+
mTriangularMesh.triangles(),
223+
trianglesInExtent );
224+
}
225+
226+
// native mesh
227+
if ( mRendererSettings.nativeMeshSettings().isEnabled() )
228+
{
229+
const QList<int> nativeFacesInExtent = QgsMeshUtils::nativeFacesFromTriangles( trianglesInExtent,
230+
mTriangularMesh.trianglesToNativeFaces() );
231+
renderMesh( mRendererSettings.nativeMeshSettings(),
232+
mNativeMesh.faces,
233+
nativeFacesInExtent );
234+
}
235+
};
236+
237+
void QgsMeshLayerRenderer::renderMesh( const QgsMeshRendererMeshSettings &settings, const QVector<QgsMeshFace> &faces, const QList<int> facesInExtent )
238+
{
239+
Q_ASSERT( settings.isEnabled() );
240+
221241
// Set up the render configuration options
222242
QPainter *painter = mContext.painter();
223243
painter->save();
@@ -238,27 +258,28 @@ void QgsMeshLayerRenderer::renderMesh(const QgsMeshRendererMeshSettings& setting
238258
const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices(); //Triangular mesh vertices contains also native mesh vertices
239259
QSet<QPair<int, int>> drawnEdges;
240260

241-
for ( int i = 0; i < faces.size(); ++i )
261+
for ( const int i : facesInExtent )
242262
{
243263
if ( mContext.renderingStopped() )
244264
break;
245265

246266
const QgsMeshFace &face = faces[i];
247-
if (face.size() < 2)
267+
if ( face.size() < 2 )
248268
continue;
249269

250-
for (int j=0; j<face.size(); ++j) {
270+
for ( int j = 0; j < face.size(); ++j )
271+
{
251272
const int startVertexId = face[j];
252-
const int endVertexId = face[ (j + 1) % face.size()];
253-
const QPair<int, int> thisEdge(startVertexId, endVertexId);
254-
const QPair<int, int> thisEdgeReversed(endVertexId, startVertexId);
255-
if (drawnEdges.contains(thisEdge) || drawnEdges.contains(thisEdgeReversed))
273+
const int endVertexId = face[( j + 1 ) % face.size()];
274+
const QPair<int, int> thisEdge( startVertexId, endVertexId );
275+
const QPair<int, int> thisEdgeReversed( endVertexId, startVertexId );
276+
if ( drawnEdges.contains( thisEdge ) || drawnEdges.contains( thisEdgeReversed ) )
256277
continue;
257-
drawnEdges.insert(thisEdge);
258-
drawnEdges.insert(thisEdgeReversed);
278+
drawnEdges.insert( thisEdge );
279+
drawnEdges.insert( thisEdgeReversed );
259280

260-
const QgsMeshVertex & startVertex = vertices[startVertexId];
261-
const QgsMeshVertex & endVertex = vertices[endVertexId];
281+
const QgsMeshVertex &startVertex = vertices[startVertexId];
282+
const QgsMeshVertex &endVertex = vertices[endVertexId];
262283
const QgsPointXY lineStart = mContext.mapToPixel().transform( startVertex.x(), startVertex.y() );
263284
const QgsPointXY lineEnd = mContext.mapToPixel().transform( endVertex.x(), endVertex.y() );
264285
painter->drawLine( lineStart.toQPointF(), lineEnd.toQPointF() );

‎src/core/mesh/qgsmeshlayerrenderer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ class QgsMeshLayerRenderer : public QgsMapLayerRenderer
9090
bool render() override;
9191

9292
private:
93-
void renderMesh(const QgsMeshRendererMeshSettings& settings, const QVector<QgsMeshFace> &faces);
93+
void renderMesh();
94+
void renderMesh( const QgsMeshRendererMeshSettings &settings, const QVector<QgsMeshFace> &faces, const QList<int> facesInExtent );
9495
void renderScalarDataset();
9596
void renderVectorDataset();
9697
void copyScalarDatasetValues( QgsMeshLayer *layer );

‎src/core/mesh/qgsmeshvectorrenderer.cpp

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,14 @@ void QgsMeshVectorRenderer::draw()
9292
pen.setColor( mCfg.color() );
9393
painter->setPen( pen );
9494

95+
const QList<int> trianglesInExtent = mTriangularMesh.faceIndexesForRectangle( mContext.extent() );
96+
9597
if ( mCfg.isOnUserDefinedGrid() )
96-
drawVectorDataOnGrid();
98+
drawVectorDataOnGrid( trianglesInExtent );
9799
else if ( mDataOnVertices )
98-
drawVectorDataOnVertices();
100+
drawVectorDataOnVertices( trianglesInExtent );
99101
else
100-
drawVectorDataOnFaces();
102+
drawVectorDataOnFaces( trianglesInExtent );
101103

102104
painter->restore();
103105
}
@@ -190,39 +192,50 @@ bool QgsMeshVectorRenderer::calcVectorLineEnd(
190192
}
191193

192194

193-
void QgsMeshVectorRenderer::drawVectorDataOnVertices()
195+
void QgsMeshVectorRenderer::drawVectorDataOnVertices( const QList<int> &trianglesInExtent )
194196
{
195197
const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices();
198+
const QVector<QgsMeshFace> &triangles = mTriangularMesh.triangles();
199+
QSet<int> drawnVertices;
196200

197201
// currently expecting that triangulation does not add any new extra vertices on the way
198202
Q_ASSERT( mDatasetValuesMag.count() == vertices.count() );
199203

200-
for ( int i = 0; i < vertices.size(); ++i )
204+
for ( int triangleIndex : trianglesInExtent )
201205
{
202206
if ( mContext.renderingStopped() )
203207
break;
204208

205-
const QgsMeshVertex &vertex = vertices.at( i );
206-
if ( !mContext.extent().contains( vertex ) )
207-
continue;
209+
const QgsMeshFace triangle = triangles[triangleIndex];
210+
for ( int i : triangle )
211+
{
212+
if ( drawnVertices.contains( i ) )
213+
continue;
214+
drawnVertices.insert( i );
208215

209-
double xVal = mDatasetValuesX[i];
210-
double yVal = mDatasetValuesY[i];
211-
if ( nodataValue( xVal, yVal ) )
212-
continue;
216+
const QgsMeshVertex &vertex = vertices.at( i );
217+
if ( !mContext.extent().contains( vertex ) )
218+
continue;
213219

214-
double V = mDatasetValuesMag[i]; // pre-calculated magnitude
215-
QgsPointXY lineStart = mContext.mapToPixel().transform( vertex.x(), vertex.y() );
220+
double xVal = mDatasetValuesX[i];
221+
double yVal = mDatasetValuesY[i];
222+
if ( nodataValue( xVal, yVal ) )
223+
continue;
216224

217-
drawVectorArrow( lineStart, xVal, yVal, V );
225+
double V = mDatasetValuesMag[i]; // pre-calculated magnitude
226+
QgsPointXY lineStart = mContext.mapToPixel().transform( vertex.x(), vertex.y() );
227+
228+
drawVectorArrow( lineStart, xVal, yVal, V );
229+
}
218230
}
219231
}
220232

221-
void QgsMeshVectorRenderer::drawVectorDataOnFaces()
233+
void QgsMeshVectorRenderer::drawVectorDataOnFaces( const QList<int> &trianglesInExtent )
222234
{
223235
const QVector<QgsMeshVertex> &centroids = mTriangularMesh.centroids();
224-
225-
for ( int i = 0; i < centroids.count(); i++ )
236+
const QList<int> nativeFacesInExtent = QgsMeshUtils::nativeFacesFromTriangles( trianglesInExtent,
237+
mTriangularMesh.trianglesToNativeFaces() );
238+
for ( int i : nativeFacesInExtent )
226239
{
227240
if ( mContext.renderingStopped() )
228241
break;
@@ -243,15 +256,15 @@ void QgsMeshVectorRenderer::drawVectorDataOnFaces()
243256
}
244257
}
245258

246-
void QgsMeshVectorRenderer::drawVectorDataOnGrid()
259+
void QgsMeshVectorRenderer::drawVectorDataOnGrid( const QList<int> &trianglesInExtent )
247260
{
248261
int cellx = mCfg.userGridCellWidth();
249262
int celly = mCfg.userGridCellHeight();
250263

251264
const QVector<QgsMeshFace> &triangles = mTriangularMesh.triangles();
252265
const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices();
253266

254-
for ( int i = 0; i < triangles.size(); i++ )
267+
for ( const int i : trianglesInExtent )
255268
{
256269
if ( mContext.renderingStopped() )
257270
break;
@@ -263,11 +276,8 @@ void QgsMeshVectorRenderer::drawVectorDataOnGrid()
263276

264277
const int nativeFaceIndex = mTriangularMesh.trianglesToNativeFaces()[i];
265278

266-
QgsRectangle bbox = QgsMeshLayerUtils::triangleBoundingBox( p1, p2, p3 );
267-
if ( !mContext.extent().intersects( bbox ) )
268-
continue;
269-
270279
// Get the BBox of the element in pixels
280+
QgsRectangle bbox = QgsMeshLayerUtils::triangleBoundingBox( p1, p2, p3 );
271281
int left, right, top, bottom;
272282
QgsMeshLayerUtils::boundingBoxToScreenRectangle( mContext.mapToPixel(), mOutputSize, bbox, left, right, top, bottom );
273283

‎src/core/mesh/qgsmeshvectorrenderer.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ class QgsMeshVectorRenderer
6565

6666
private:
6767
//! Draws for data defined on vertices
68-
void drawVectorDataOnVertices();
68+
void drawVectorDataOnVertices( const QList<int> &trianglesInExtent );
6969
//! Draws for data defined on face centers
70-
void drawVectorDataOnFaces();
70+
void drawVectorDataOnFaces( const QList<int> &trianglesInExtent );
7171
//! Draws data on user-defined grid
72-
void drawVectorDataOnGrid();
72+
void drawVectorDataOnGrid( const QList<int> &trianglesInExtent );
7373
//! Draws arrow from start point and vector data
7474
void drawVectorArrow( const QgsPointXY &lineStart, double xVal, double yVal, double magnitude );
7575
//! Calculates the end point of the arrow based on start point and vector data

‎src/core/mesh/qgstriangularmesh.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ bool QgsMeshFeatureIterator::fetchFeature( QgsFeature &f )
5555
const QgsMeshFace &face = mMesh->faces.at( it ) ;
5656
QgsGeometry geom = QgsMeshUtils::toGeometry( face, mMesh->vertices );
5757
f.setGeometry( geom );
58+
f.setId( it );
5859
++it;
5960
return true;
6061
}
@@ -232,6 +233,18 @@ int QgsTriangularMesh::faceIndexForPoint( const QgsPointXY &point ) const
232233
return -1;
233234
}
234235

236+
QList<int> QgsTriangularMesh::faceIndexesForRectangle( const QgsRectangle &rectangle ) const
237+
{
238+
const QList<QgsFeatureId> faceIndexes = mSpatialIndex.intersects( rectangle );
239+
QList<int> indexes;
240+
for ( const QgsFeatureId fid : faceIndexes )
241+
{
242+
int faceIndex = static_cast<int>( fid );
243+
indexes.append( faceIndex );
244+
}
245+
return indexes;
246+
}
247+
235248
QgsGeometry QgsMeshUtils::toGeometry( const QgsMeshFace &face, const QVector<QgsMeshVertex> &vertices )
236249
{
237250
QVector<QgsPoint> ring;
@@ -246,3 +259,14 @@ QgsGeometry QgsMeshUtils::toGeometry( const QgsMeshFace &face, const QVector<Qgs
246259
polygon->setExteriorRing( new QgsLineString( ring ) );
247260
return QgsGeometry( std::move( polygon ) );
248261
}
262+
263+
QList<int> QgsMeshUtils::nativeFacesFromTriangles( const QList<int> &triangleIndexes, const QVector<int> &trianglesToNativeFaces )
264+
{
265+
QSet<int> nativeFaces;
266+
for ( const int triangleIndex : triangleIndexes )
267+
{
268+
const int nativeIndex = trianglesToNativeFaces[triangleIndex];
269+
nativeFaces.insert( nativeIndex );
270+
}
271+
return nativeFaces.toList();
272+
}

‎src/core/mesh/qgstriangularmesh.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
class QgsRenderContext;
3333
class QgsCoordinateTransform;
34+
class QgsRectangle;
3435

3536
//! Mesh - vertices and faces
3637
struct CORE_EXPORT QgsMesh
@@ -124,6 +125,17 @@ class CORE_EXPORT QgsTriangularMesh
124125
*/
125126
int faceIndexForPoint( const QgsPointXY &point ) const ;
126127

128+
/**
129+
* Finds indexes of triangles intersecting given bounding box
130+
* It uses spatial indexing
131+
*
132+
* \param rectangle bounding box in map coordinate system
133+
* \returns triangle indexes that intersect the rectangle
134+
*
135+
* \since QGIS 3.4
136+
*/
137+
QList<int> faceIndexesForRectangle( const QgsRectangle &rectangle ) const ;
138+
127139
private:
128140
// vertices: map CRS; 0-N ... native vertices, N+1 - len ... extra vertices
129141
// faces are derived triangles
@@ -141,6 +153,12 @@ namespace QgsMeshUtils
141153
{
142154
//! Returns face as polygon geometry
143155
QgsGeometry toGeometry( const QgsMeshFace &face, const QVector<QgsMeshVertex> &vertices );
156+
157+
/**
158+
* Returns unique native faces indexes from list of triangle indexes
159+
* \since QGIS 3.4
160+
*/
161+
QList<int> nativeFacesFromTriangles( const QList<int> &triangleIndexes, const QVector<int> &trianglesToNativeFaces );
144162
};
145163

146164
#endif // QGSTRIANGULARMESH_H

0 commit comments

Comments
 (0)