QGIS API Documentation  3.2.0-Bonn (bc43194)
qgsmeshlayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmeshlayer.cpp
3  ----------------
4  begin : April 2018
5  copyright : (C) 2018 by Peter Petrik
6  email : zilolv at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include <cstddef>
19 
20 #include <QUuid>
21 
22 
23 #include "qgslogger.h"
24 #include "qgsmeshdataprovider.h"
25 #include "qgsmeshlayer.h"
26 #include "qgsmeshlayerrenderer.h"
27 #include "qgsproviderregistry.h"
28 #include "qgsreadwritecontext.h"
29 #include "qgstriangularmesh.h"
30 
31 QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
32  const QString &baseName,
33  const QString &providerKey,
34  const LayerOptions & )
35  : QgsMapLayer( MeshLayer, baseName, meshLayerPath )
36  , mProviderKey( providerKey )
37 {
38  // load data
39  QgsDataProvider::ProviderOptions providerOptions;
40  setDataProvider( providerKey, providerOptions );
41 
42  // show at least the mesh by default so we render something
43  mRendererNativeMeshSettings.setEnabled( true );
44 
45 } // QgsMeshLayer ctor
46 
47 
48 
50 {
51  if ( mDataProvider )
52  delete mDataProvider;
53 }
54 
56 {
57  return mDataProvider;
58 }
59 
61 {
62  return mDataProvider;
63 }
64 
66 {
67  QgsMeshLayer *layer = new QgsMeshLayer( source(), name(), mProviderKey );
68  QgsMapLayer::clone( layer );
69  return layer;
70 }
71 
73 {
74  if ( mDataProvider )
75  return mDataProvider->extent();
76  else
77  {
78  QgsRectangle rec;
79  rec.setMinimal();
80  return rec;
81  }
82 }
83 
85 {
86  return mProviderKey;
87 }
88 
90 {
91  return mNativeMesh.get();
92 }
93 
94 
96 {
97  return mTriangularMesh.get();
98 }
99 
100 
102 {
103  return mRendererNativeMeshSettings;
104 }
105 
107 {
108  mRendererNativeMeshSettings = settings;
109  triggerRepaint();
110 }
111 
113 {
114  return mRendererTriangularMeshSettings;
115 }
116 
118 {
119  mRendererTriangularMeshSettings = settings;
120  triggerRepaint();
121 }
122 
124 {
125  return mRendererScalarSettings;
126 }
127 
129 {
130  mRendererScalarSettings = settings;
131  triggerRepaint();
132 }
133 
134 
136 {
137  return mRendererVectorSettings;
138 }
139 
141 {
142  mRendererVectorSettings = settings;
143  triggerRepaint();
144 }
145 
146 
148 {
149  if ( index == mActiveScalarDataset )
150  return;
151 
152  if ( ( index >= 0 ) && ( index < dataProvider()->datasetCount() ) )
153  mActiveScalarDataset = index;
154  else
155  mActiveScalarDataset = NO_ACTIVE_MESH_DATASET;
156 
157  triggerRepaint();
158 }
159 
161 {
162  if ( index == mActiveVectorDataset )
163  return;
164 
165  if ( ( index < 0 ) || ( index >= dataProvider()->datasetCount() ) )
166  {
167  mActiveVectorDataset = NO_ACTIVE_MESH_DATASET;
168  }
169  else
170  {
172  if ( metadata.isVector() )
173  mActiveVectorDataset = index;
174  else
175  mActiveVectorDataset = NO_ACTIVE_MESH_DATASET;
176  }
177 
178  triggerRepaint();
179 }
180 
181 void QgsMeshLayer::fillNativeMesh()
182 {
183  Q_ASSERT( !mNativeMesh );
184 
185  mNativeMesh.reset( new QgsMesh() );
186 
187  if ( !( dataProvider() && dataProvider()->isValid() ) )
188  return;
189 
190  mNativeMesh->vertices.resize( dataProvider()->vertexCount() );
191  for ( int i = 0; i < dataProvider()->vertexCount(); ++i )
192  {
193  mNativeMesh->vertices[i] = dataProvider()->vertex( i );
194  }
195 
196  mNativeMesh->faces.resize( dataProvider()->faceCount() );
197  for ( int i = 0; i < dataProvider()->faceCount(); ++i )
198  {
199  mNativeMesh->faces[i] = dataProvider()->face( i );
200  }
201 }
202 
204 {
205  if ( !mNativeMesh )
206  {
207  // lazy loading of mesh data
208  fillNativeMesh();
209  }
210 
211  if ( !mTriangularMesh )
212  mTriangularMesh.reset( new QgsTriangularMesh() );
213 
214  mTriangularMesh->update( mNativeMesh.get(), &rendererContext );
215  return new QgsMeshLayerRenderer( this, rendererContext );
216 }
217 
218 bool QgsMeshLayer::readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context )
219 {
220  Q_UNUSED( node );
221  Q_UNUSED( errorMessage );
222  Q_UNUSED( context );
223  return true;
224 }
225 
226 bool QgsMeshLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const
227 {
228  Q_UNUSED( node );
229  Q_UNUSED( doc );
230  Q_UNUSED( errorMessage );
231  Q_UNUSED( context );
232  return true;
233 }
234 
235 QString QgsMeshLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
236 {
237  QString src( source );
238  if ( provider == QLatin1String( "mdal" ) )
239  {
240  src = context.pathResolver().readPath( src );
241  }
242  return src;
243 }
244 
245 QString QgsMeshLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
246 {
247  QString src( source );
248  if ( providerType() == QLatin1String( "mdal" ) )
249  {
250  src = context.pathResolver().writePath( src );
251  }
252  return src;
253 }
254 
255 bool QgsMeshLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
256 {
257  Q_UNUSED( context );
258 
259  QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsMeshLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
260 
261  //process provider key
262  QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
263 
264  if ( pkeyNode.isNull() )
265  {
266  mProviderKey.clear();
267  }
268  else
269  {
270  QDomElement pkeyElt = pkeyNode.toElement();
271  mProviderKey = pkeyElt.text();
272  }
273 
274  QgsDataProvider::ProviderOptions providerOptions;
275  if ( !setDataProvider( mProviderKey, providerOptions ) )
276  {
277  return false;
278  }
279 
280  return mValid; // should be true if read successfully
281 }
282 
283 bool QgsMeshLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
284 {
285  // first get the layer element so that we can append the type attribute
286  QDomElement mapLayerNode = layer_node.toElement();
287 
288  if ( mapLayerNode.isNull() || ( QLatin1String( "maplayer" ) != mapLayerNode.nodeName() ) )
289  {
290  QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
291  return false;
292  }
293 
294  mapLayerNode.setAttribute( QStringLiteral( "type" ), QStringLiteral( "mesh" ) );
295 
296  // add provider node
297  if ( mDataProvider )
298  {
299  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
300  QDomText providerText = document.createTextNode( providerType() );
301  provider.appendChild( providerText );
302  layer_node.appendChild( provider );
303  }
304 
305  // renderer specific settings
306  QString errorMsg;
307  return writeSymbology( layer_node, document, errorMsg, context );
308 }
309 
310 bool QgsMeshLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options )
311 {
312  if ( mDataProvider )
313  delete mDataProvider;
314 
315  mProviderKey = provider;
316  QString dataSource = mDataSource;
317 
318  mDataProvider = qobject_cast<QgsMeshDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, dataSource, options ) );
319  if ( !mDataProvider )
320  {
321  QgsDebugMsgLevel( QStringLiteral( "Unable to get mesh data provider" ), 2 );
322  return false;
323  }
324 
325  mDataProvider->setParent( this );
326  QgsDebugMsgLevel( QStringLiteral( "Instantiated the mesh data provider plugin" ), 2 );
327 
328  mValid = mDataProvider->isValid();
329  if ( !mValid )
330  {
331  QgsDebugMsgLevel( QStringLiteral( "Invalid mesh provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
332  return false;
333  }
334 
335  if ( provider == QStringLiteral( "mesh_memory" ) )
336  {
337  // required so that source differs between memory layers
338  mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
339  }
340 
341  return true;
342 } // QgsMeshLayer:: setDataProvider
QgsMeshRendererVectorSettings rendererVectorSettings() const
Returns renderer settings.
The class is used as a container of context for various read/write operations on other objects...
A rectangle specified with double values.
Definition: qgsrectangle.h:40
Base class for all map layer types.
Definition: qgsmaplayer.h:61
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context) const override
Write the symbology for the layer into the docment provided.
bool readSymbology(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context) override
Read the symbology for the current layer from the Dom node supplied.
Triangular/Derived Mesh.
QgsMeshRendererMeshSettings rendererTriangularMeshSettings() const
Returns renderer settings.
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:150
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
void setRendererNativeMeshSettings(const QgsMeshRendererMeshSettings &settings)
Sets new renderer settings, triggers repaint.
virtual int faceCount() const =0
Returns number of faces in the native mesh.
void setActiveScalarDataset(int index=NO_ACTIVE_MESH_DATASET)
Sets active scalar dataset for rendering.
Represents a mesh renderer settings for mesh object.
virtual QgsMeshDatasetMetadata datasetMetadata(int datasetIndex) const =0
Returns dataset metadata.
Represents a mesh renderer settings for scalar datasets.
virtual int vertexCount() const =0
Returns number of vertices in the native mesh.
QString encodedSource(const QString &source, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by derived classes to encode provider&#39;s specific data source to proje...
bool isVector() const
Returns whether dataset has vector data.
virtual const QgsLayerMetadata & metadata() const
Returns a reference to the layer&#39;s metadata store.
Setting options for loading mesh layers.
Definition: qgsmeshlayer.h:98
bool isValid() const
Returns the status of the layer.
void setRendererVectorSettings(const QgsMeshRendererVectorSettings &settings)
Sets new renderer settings, triggers repaint.
QgsMesh * nativeMesh()
Returns native mesh (nullptr before rendering)
const int NO_ACTIVE_MESH_DATASET
Definition: qgsmeshlayer.h:29
Implementation of threaded rendering for mesh layers.
QgsRectangle extent() const override
Returns the extent of the layer.
QgsDataProvider * createProvider(const QString &providerKey, const QString &dataSource, const QgsDataProvider::ProviderOptions &options=QgsDataProvider::ProviderOptions())
Creates a new instance of a provider.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QgsRectangle extent() const override
Returns the extent of the layer.
Represents a mesh renderer settings for vector datasets.
QString providerType() const
Returns the provider type for this layer.
void setRendererTriangularMeshSettings(const QgsMeshRendererMeshSettings &settings)
Sets new renderer settings, triggers repaint.
QgsMeshRendererMeshSettings rendererNativeMeshSettings() const
Returns renderer settings.
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted...
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define SIP_SKIP
Definition: qgis_sip.h:119
virtual bool isValid() const =0
Returns true if this is a valid layer.
~QgsMeshLayer() override
void setRendererScalarSettings(const QgsMeshRendererScalarSettings &settings)
Sets new renderer settings, triggers repaint.
QString decodedSource(const QString &source, const QString &provider, const QgsReadWriteContext &context) const override
Called by readLayerXML(), used by derived classes to decode provider&#39;s specific data source from proj...
QgsMeshDataProvider * dataProvider() override
Returns the layer&#39;s data provider.
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:1269
void setEnabled(bool enabled)
Sets whether mesh structure rendering is enabled.
QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) override
Returns new instance of QgsMapLayerRenderer that will be used for rendering of given context...
Base class for providing data for QgsMeshLayer.
virtual QgsMeshVertex vertex(int index) const =0
Returns the mesh vertex at index.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
bool writeXml(QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by children to write state specific to them to project files...
Contains information about the context of a rendering operation.
Setting options for creating vector data providers.
QString name() const
Returns the display name of the layer.
virtual QgsMeshFace face(int index) const =0
Returns the mesh face at index.
Mesh - vertices and faces.
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:1272
QString source() const
Returns the source for the layer.
void setActiveVectorDataset(int index=NO_ACTIVE_MESH_DATASET)
Sets active vector dataset for rendering.
QgsMeshLayer * clone() const override
Returns a new instance equivalent to this one except for the id which is still unique.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
Base class for utility classes that encapsulate information necessary for rendering of map layers...
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:90
QgsMeshDatasetMetadata is a collection of mesh dataset metadata such as whether the data is vector or...
QgsMeshRendererScalarSettings rendererScalarSettings() const
Returns renderer settings.
bool readXml(const QDomNode &layer_node, QgsReadWriteContext &context) override
Called by readLayerXML(), used by children to read state specific to them from project files...
QgsTriangularMesh * triangularMesh()
Returns triangular mesh (nullptr before rendering)
QgsMeshLayer(const QString &path=QString(), const QString &baseName=QString(), const QString &providerLib="mesh_memory", const QgsMeshLayer::LayerOptions &options=QgsMeshLayer::LayerOptions())
Constructor - creates a mesh layer.