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

Mesh fixes1 #15

Closed
wants to merge 8 commits into from
Closed
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
2 changes: 1 addition & 1 deletion external/mdal/mdal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ static MDAL_Status sLastStatus;

const char *MDAL_Version()
{
return "0.0.7";
return "0.0.8";
}

MDAL_Status MDAL_LastStatus()
Expand Down
2 changes: 1 addition & 1 deletion external/mdal/mdal_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ MDAL::BBox MDAL::computeExtent( const MDAL::Vertices &vertices )
{
BBox b;

if ( vertices.empty() == 0 )
if ( vertices.empty() )
return b;

b.minX = vertices[0].x;
Expand Down
1 change: 1 addition & 0 deletions python/core/auto_generated/mesh/qgsmeshlayer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ Returns the provider type for this layer




QgsMeshRendererSettings rendererSettings() const;
%Docstring
Returns renderer settings
Expand Down
14 changes: 14 additions & 0 deletions src/core/mesh/qgsmeshlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ QgsTriangularMesh *QgsMeshLayer::triangularMesh() SIP_SKIP
return mTriangularMesh.get();
}

QgsMeshLayerRendererCache *QgsMeshLayer::rendererCache()
{
return mRendererCache.get();
}

QgsMeshRendererSettings QgsMeshLayer::rendererSettings() const
{
return mRendererSettings;
Expand Down Expand Up @@ -229,16 +234,23 @@ void QgsMeshLayer::assignDefaultStyleToDatasetGroup( int groupIndex )

QgsMapLayerRenderer *QgsMeshLayer::createMapRenderer( QgsRenderContext &rendererContext )
{
// Native mesh
if ( !mNativeMesh )
{
// lazy loading of mesh data
fillNativeMesh();
}

// Triangular mesh
if ( !mTriangularMesh )
mTriangularMesh.reset( new QgsTriangularMesh() );

mTriangularMesh->update( mNativeMesh.get(), &rendererContext );

// Cache
if ( !mRendererCache )
mRendererCache.reset( new QgsMeshLayerRendererCache() );

return new QgsMeshLayerRenderer( this, rendererContext );
}

Expand Down Expand Up @@ -405,6 +417,8 @@ bool QgsMeshLayer::setDataProvider( QString const &provider, const QgsDataProvid
return false;
}

setCrs( mDataProvider->crs() );

if ( provider == QStringLiteral( "mesh_memory" ) )
{
// required so that source differs between memory layers
Expand Down
7 changes: 7 additions & 0 deletions src/core/mesh/qgsmeshlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "qgsmeshrenderersettings.h"

class QgsMapLayerRenderer;
struct QgsMeshLayerRendererCache;
class QgsSymbol;
class QgsTriangularMesh;
struct QgsMesh;
Expand Down Expand Up @@ -143,6 +144,9 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer
//! Returns triangular mesh (nullptr before rendering)
QgsTriangularMesh *triangularMesh() SIP_SKIP;

//! Returns native mesh (nullptr before rendering)
QgsMeshLayerRendererCache *rendererCache() SIP_SKIP;

//! Returns renderer settings
QgsMeshRendererSettings rendererSettings() const;
//! Sets new renderer settings
Expand Down Expand Up @@ -219,6 +223,9 @@ class CORE_EXPORT QgsMeshLayer : public QgsMapLayer
//! Pointer to derived mesh structure
std::unique_ptr<QgsTriangularMesh> mTriangularMesh;

//! Pointer to the cache with data used for last rendering
std::unique_ptr<QgsMeshLayerRendererCache> mRendererCache;

//! Renderer configuration
QgsMeshRendererSettings mRendererSettings;
};
Expand Down
3 changes: 3 additions & 0 deletions src/core/mesh/qgsmeshlayerinterpolator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ QgsRasterBlock *QgsMeshLayerInterpolator::block( int, const QgsRectangle &extent
if ( feedback && feedback->isCanceled() )
break;

if ( mContext.renderingStopped() )
break;

const QgsMeshFace &face = triangles[i];

const int v1 = face[0], v2 = face[1], v3 = face[2];
Expand Down
164 changes: 126 additions & 38 deletions src/core/mesh/qgsmeshlayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
***************************************************************************/

#include <memory>
#include <QSet>
#include <QPair>

#include "qgsmeshlayerrenderer.h"

Expand All @@ -24,8 +26,6 @@
#include "qgsmeshlayer.h"
#include "qgspointxy.h"
#include "qgsrenderer.h"
#include "qgssinglesymbolrenderer.h"
#include "qgssymbol.h"
#include "qgssinglebandpseudocolorrenderer.h"
#include "qgsrastershader.h"
#include "qgsmeshlayerinterpolator.h"
Expand All @@ -45,12 +45,12 @@ QgsMeshLayerRenderer::QgsMeshLayerRenderer( QgsMeshLayer *layer, QgsRenderContex
// make copies for mesh data
Q_ASSERT( layer->nativeMesh() );
Q_ASSERT( layer->triangularMesh() );
Q_ASSERT( layer->rendererCache() );
Q_ASSERT( layer->dataProvider() );

mNativeMesh = *( layer->nativeMesh() );
mTriangularMesh = *( layer->triangularMesh() );

createMeshSymbol( mNativeMeshSymbol, mRendererSettings.nativeMeshSettings() );
createMeshSymbol( mTriangularMeshSymbol, mRendererSettings.triangularMeshSettings() );

copyScalarDatasetValues( layer );
copyVectorDatasetValues( layer );

Expand All @@ -74,25 +74,25 @@ void QgsMeshLayerRenderer::calculateOutputSize()
mOutputSize = QSize( width, height );
}

void QgsMeshLayerRenderer::createMeshSymbol( std::unique_ptr<QgsSymbol> &symbol,
const QgsMeshRendererMeshSettings &settings )
void QgsMeshLayerRenderer::copyScalarDatasetValues( QgsMeshLayer *layer )
{
if ( settings.isEnabled() )
const QgsMeshDatasetIndex datasetIndex = mRendererSettings.activeScalarDataset();

// Find out if we can use cache up to date. If yes, use it and return
const int datasetGroupCount = layer->dataProvider()->datasetGroupCount();
QgsMeshLayerRendererCache *cache = layer->rendererCache();
if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
( cache->mActiveScalarDatasetIndex == datasetIndex ) )
{
QgsSymbolLayerList l1;
l1 << new QgsSimpleFillSymbolLayer( Qt::white,
Qt::NoBrush,
settings.color(),
Qt::SolidLine,
settings.lineWidth() );
symbol.reset( new QgsFillSymbol( l1 ) );
mScalarDatasetValues = cache->mScalarDatasetValues;
mScalarActiveFaceFlagValues = cache->mScalarActiveFaceFlagValues;
mScalarDataOnVertices = cache->mScalarDataOnVertices;
mScalarDatasetMinimum = cache->mScalarDatasetMinimum;
mScalarDatasetMaximum = cache->mScalarDatasetMaximum;
return;
}
}


void QgsMeshLayerRenderer::copyScalarDatasetValues( QgsMeshLayer *layer )
{
const QgsMeshDatasetIndex datasetIndex = mRendererSettings.activeScalarDataset();
// Cache is not up-to-date, gather data
if ( datasetIndex.isValid() )
{
const QgsMeshDatasetGroupMetadata metadata = layer->dataProvider()->datasetGroupMetadata( datasetIndex );
Expand Down Expand Up @@ -120,11 +120,38 @@ void QgsMeshLayerRenderer::copyScalarDatasetValues( QgsMeshLayer *layer )

QgsMeshLayerUtils::calculateMinimumMaximum( mScalarDatasetMinimum, mScalarDatasetMaximum, mScalarDatasetValues );
}

// update cache
cache->mDatasetGroupsCount = datasetGroupCount;
cache->mActiveScalarDatasetIndex = datasetIndex;
cache->mScalarDatasetValues = mScalarDatasetValues;
cache->mScalarActiveFaceFlagValues = mScalarActiveFaceFlagValues;
cache->mScalarDataOnVertices = mScalarDataOnVertices;
cache->mScalarDatasetMinimum = mScalarDatasetMinimum;
cache->mScalarDatasetMaximum = mScalarDatasetMaximum;
}

void QgsMeshLayerRenderer::copyVectorDatasetValues( QgsMeshLayer *layer )
{
const QgsMeshDatasetIndex datasetIndex = mRendererSettings.activeVectorDataset();

// Find out if we can use cache up to date. If yes, use it and return
const int datasetGroupCount = layer->dataProvider()->datasetGroupCount();
QgsMeshLayerRendererCache *cache = layer->rendererCache();
if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
( cache->mActiveVectorDatasetIndex == datasetIndex ) )
{
mVectorDatasetValuesX = cache->mVectorDatasetValuesX;
mVectorDatasetValuesY = cache->mVectorDatasetValuesY;
mVectorDatasetValuesMag = cache->mVectorDatasetValuesMag;
mVectorDatasetMagMinimum = cache->mVectorDatasetMagMinimum;
mVectorDatasetMagMaximum = cache->mVectorDatasetMagMaximum;
mVectorDataOnVertices = cache->mVectorDataOnVertices;
return;
}


// Cache is not up-to-date, gather data
if ( datasetIndex.isValid() )
{
const QgsMeshDatasetGroupMetadata metadata = layer->dataProvider()->datasetGroupMetadata( datasetIndex );
Expand Down Expand Up @@ -161,44 +188,105 @@ void QgsMeshLayerRenderer::copyVectorDatasetValues( QgsMeshLayer *layer )

QgsMeshLayerUtils::calculateMinimumMaximum( mVectorDatasetMagMinimum, mVectorDatasetMagMaximum, mVectorDatasetValuesMag );
}

// update cache
cache->mDatasetGroupsCount = datasetGroupCount;
cache->mActiveVectorDatasetIndex = datasetIndex;
cache->mVectorDatasetValuesX = mVectorDatasetValuesX;
cache->mVectorDatasetValuesY = mVectorDatasetValuesY;
cache->mVectorDatasetValuesMag = mVectorDatasetValuesMag;
cache->mVectorDatasetMagMinimum = mVectorDatasetMagMinimum;
cache->mVectorDatasetMagMaximum = mVectorDatasetMagMaximum;
cache->mVectorDataOnVertices = mVectorDataOnVertices;
}

bool QgsMeshLayerRenderer::render()
{

renderScalarDataset();

renderMesh( mNativeMeshSymbol, mNativeMesh.faces ); // native mesh
renderMesh( mTriangularMeshSymbol, mTriangularMesh.triangles() ); // triangular mesh

renderMesh();
renderVectorDataset();

return true;
}

void QgsMeshLayerRenderer::renderMesh( const std::unique_ptr<QgsSymbol> &symbol, const QVector<QgsMeshFace> &faces )
void QgsMeshLayerRenderer::renderMesh()
{
if ( !symbol )
if ( !mRendererSettings.nativeMeshSettings().isEnabled() &&
!mRendererSettings.triangularMeshSettings().isEnabled() )
return;

QgsFields fields;
QgsSingleSymbolRenderer renderer( symbol->clone() );
renderer.startRender( mContext, fields );
// triangular mesh
const QList<int> trianglesInExtent = mTriangularMesh.faceIndexesForRectangle( mContext.extent() );
if ( mRendererSettings.triangularMeshSettings().isEnabled() )
{
renderMesh( mRendererSettings.triangularMeshSettings(),
mTriangularMesh.triangles(),
trianglesInExtent );
}

// native mesh
if ( mRendererSettings.nativeMeshSettings().isEnabled() )
{
const QList<int> nativeFacesInExtent = QgsMeshUtils::nativeFacesFromTriangles( trianglesInExtent,
mTriangularMesh.trianglesToNativeFaces() );
renderMesh( mRendererSettings.nativeMeshSettings(),
mNativeMesh.faces,
nativeFacesInExtent );
}
};

void QgsMeshLayerRenderer::renderMesh( const QgsMeshRendererMeshSettings &settings, const QVector<QgsMeshFace> &faces, const QList<int> facesInExtent )
{
Q_ASSERT( settings.isEnabled() );

// Set up the render configuration options
QPainter *painter = mContext.painter();
painter->save();
if ( mContext.flags() & QgsRenderContext::Antialiasing )
painter->setRenderHint( QPainter::Antialiasing, true );

painter->setRenderHint( QPainter::Antialiasing );
QPen pen = painter->pen();
pen.setCapStyle( Qt::FlatCap );
pen.setJoinStyle( Qt::MiterJoin );

double penWidth = mContext.convertToPainterUnits( settings.lineWidth(),
QgsUnitTypes::RenderUnit::RenderMillimeters );
pen.setWidthF( penWidth );
pen.setColor( settings.color() );
painter->setPen( pen );

for ( int i = 0; i < faces.size(); ++i )
const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices(); //Triangular mesh vertices contains also native mesh vertices
QSet<QPair<int, int>> drawnEdges;

for ( const int i : facesInExtent )
{
if ( mContext.renderingStopped() )
break;

const QgsMeshFace &face = faces[i];
QgsFeature feat;
feat.setFields( fields );
QgsGeometry geom = QgsMeshUtils::toGeometry( face, mTriangularMesh.vertices() ); //Triangular mesh vertices contains also native mesh vertices
feat.setGeometry( geom );
renderer.renderFeature( feat, mContext );
if ( face.size() < 2 )
continue;

for ( int j = 0; j < face.size(); ++j )
{
const int startVertexId = face[j];
const int endVertexId = face[( j + 1 ) % face.size()];
const QPair<int, int> thisEdge( startVertexId, endVertexId );
const QPair<int, int> thisEdgeReversed( endVertexId, startVertexId );
if ( drawnEdges.contains( thisEdge ) || drawnEdges.contains( thisEdgeReversed ) )
continue;
drawnEdges.insert( thisEdge );
drawnEdges.insert( thisEdgeReversed );

const QgsMeshVertex &startVertex = vertices[startVertexId];
const QgsMeshVertex &endVertex = vertices[endVertexId];
const QgsPointXY lineStart = mContext.mapToPixel().transform( startVertex.x(), startVertex.y() );
const QgsPointXY lineEnd = mContext.mapToPixel().transform( endVertex.x(), endVertex.y() );
painter->drawLine( lineStart.toQPointF(), lineEnd.toQPointF() );
}
}

renderer.stopRender( mContext );
painter->restore();
}

void QgsMeshLayerRenderer::renderScalarDataset()
Expand Down
Loading