QGIS API Documentation  3.2.0-Bonn (bc43194)
qgsmeshmemorydataprovider.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmeshmemorydataprovider.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  ***************************************************************************/
18 
20 
21 static const QString TEXT_PROVIDER_KEY = QStringLiteral( "mesh_memory" );
22 static const QString TEXT_PROVIDER_DESCRIPTION = QStringLiteral( "Mesh memory provider" );
23 
24 bool QgsMeshMemoryDataProvider::isValid() const
25 {
26  return true;
27 }
28 
29 QString QgsMeshMemoryDataProvider::name() const
30 {
31  return TEXT_PROVIDER_KEY;
32 }
33 
34 QString QgsMeshMemoryDataProvider::description() const
35 {
36  return TEXT_PROVIDER_DESCRIPTION;
37 }
38 
39 QgsCoordinateReferenceSystem QgsMeshMemoryDataProvider::crs() const
40 {
42 }
43 
44 QgsMeshMemoryDataProvider::QgsMeshMemoryDataProvider( const QString &uri, const ProviderOptions &options )
45  : QgsMeshDataProvider( uri, options )
46 {
47  mIsValid = splitMeshSections( uri );
48 }
49 
50 QString QgsMeshMemoryDataProvider::providerKey()
51 {
52  return TEXT_PROVIDER_KEY;
53 }
54 
55 QString QgsMeshMemoryDataProvider::providerDescription()
56 {
57  return TEXT_PROVIDER_DESCRIPTION;
58 }
59 
60 QgsMeshMemoryDataProvider *QgsMeshMemoryDataProvider::createProvider( const QString &uri, const ProviderOptions &options )
61 {
62  return new QgsMeshMemoryDataProvider( uri, options );
63 }
64 
65 bool QgsMeshMemoryDataProvider::splitMeshSections( const QString &uri )
66 {
67  const QStringList sections = uri.split( QStringLiteral( "---" ), QString::SkipEmptyParts );
68  if ( sections.size() != 2 )
69  {
70  setError( QgsError( tr( "Invalid mesh definition, does not contain 2 sections" ),
71  QStringLiteral( "Mesh Memory Provider" ) ) );
72  return false;
73  }
74 
75  if ( addMeshVertices( sections[0] ) )
76  return addMeshFaces( sections[1] );
77  else
78  return false;
79 }
80 
81 bool QgsMeshMemoryDataProvider::addMeshVertices( const QString &def )
82 {
83  QVector<QgsMeshVertex> vertices;
84 
85  const QStringList verticesCoords = def.split( '\n', QString::SkipEmptyParts );
86  for ( int i = 0; i < verticesCoords.size(); ++i )
87  {
88  const QStringList coords = verticesCoords[i].split( ',', QString::SkipEmptyParts );
89  if ( coords.size() != 2 )
90  {
91  setError( QgsError( tr( "Invalid mesh definition, vertex definition does not contain x, y" ),
92  QStringLiteral( "Mesh Memory Provider" ) ) );
93  return false;
94  }
95  double x = coords.at( 0 ).toDouble();
96  double y = coords.at( 1 ).toDouble();
97  QgsMeshVertex vertex( x, y );
98  vertices.push_back( vertex );
99  }
100 
101  mVertices = vertices;
102  return true;
103 }
104 
105 bool QgsMeshMemoryDataProvider::addMeshFaces( const QString &def )
106 {
107  QVector<QgsMeshFace> faces;
108 
109  const QStringList facesVertices = def.split( '\n', QString::SkipEmptyParts );
110  for ( int i = 0; i < facesVertices.size(); ++i )
111  {
112  const QStringList vertices = facesVertices[i].split( ',', QString::SkipEmptyParts );
113  if ( vertices.size() < 3 )
114  {
115  setError( QgsError( tr( "Invalid mesh definition, face must contain at least 3 vertices" ),
116  QStringLiteral( "Mesh Memory Provider" ) ) );
117  return false;
118  }
119  QgsMeshFace face;
120  for ( int j = 0; j < vertices.size(); ++j )
121  {
122  int vertex_id = vertices[j].toInt();
123  if ( vertex_id < 0 )
124  {
125  setError( QgsError( tr( "Invalid mesh definition, vertex index must be positive value" ),
126  QStringLiteral( "Mesh Memory Provider" ) ) );
127  return false;
128  }
129  if ( mVertices.size() < vertex_id )
130  {
131  setError( QgsError( tr( "Invalid mesh definition, missing vertex id defined in face" ),
132  QStringLiteral( "Mesh Memory Provider" ) ) );
133  return false;
134  }
135 
136  face.push_back( vertex_id );
137  }
138  faces.push_back( face );
139  }
140 
141  mFaces = faces;
142  return true;
143 }
144 
145 
146 bool QgsMeshMemoryDataProvider::splitDatasetSections( const QString &uri, QgsMeshMemoryDataset &dataset )
147 {
148  const QStringList sections = uri.split( QStringLiteral( "---" ), QString::SkipEmptyParts );
149 
150  bool success = sections.size() == 3;
151  if ( !success )
152  {
153  setError( QgsError( tr( "Invalid dataset definition, does not contain 3 sections" ),
154  QStringLiteral( "Mesh Memory Provider" ) ) );
155  }
156 
157  if ( success )
158  success = setDatasetType( sections[0], dataset );
159  if ( success )
160  success = addDatasetMetadata( sections[1], dataset );
161  if ( success )
162  success = addDatasetValues( sections[2], dataset );
163  if ( success )
164  success = checkDatasetValidity( dataset );
165 
166  return success;
167 }
168 
169 bool QgsMeshMemoryDataProvider::setDatasetType( const QString &def, QgsMeshMemoryDataset &dataset )
170 {
171  const QStringList types = def.split( ' ', QString::SkipEmptyParts );
172 
173  if ( types.size() != 2 )
174  {
175  setError( QgsError( tr( "Invalid type definition, must be Vertex/Face Vector/Scalar" ),
176  QStringLiteral( "Mesh Memory Provider" ) ) );
177  return false;
178  }
179 
180  dataset.isOnVertices = 0 == QString::compare( types[0].trimmed(), QStringLiteral( "vertex" ), Qt::CaseInsensitive );
181  dataset.isScalar = 0 == QString::compare( types[1].trimmed(), QStringLiteral( "scalar" ), Qt::CaseInsensitive );
182 
183  return true;
184 }
185 
186 bool QgsMeshMemoryDataProvider::addDatasetMetadata( const QString &def, QgsMeshMemoryDataset &dataset )
187 {
188  const QStringList metadataLines = def.split( '\n', QString::SkipEmptyParts );
189  for ( int i = 0; i < metadataLines.size(); ++i )
190  {
191  const QStringList keyVal = metadataLines[i].split( ':', QString::SkipEmptyParts );
192  if ( keyVal.size() != 2 )
193  {
194  setError( QgsError( tr( "Invalid dataset definition, dataset metadata does not contain key: value" ),
195  QStringLiteral( "Mesh Memory Provider" ) ) );
196  return false;
197  }
198 
199  dataset.metadata.insert( keyVal.at( 0 ).trimmed(), keyVal.at( 1 ).trimmed() );
200  }
201  return true;
202 }
203 
204 bool QgsMeshMemoryDataProvider::addDatasetValues( const QString &def, QgsMeshMemoryDataset &dataset )
205 {
206  const QStringList valuesLines = def.split( '\n', QString::SkipEmptyParts );
207  for ( int i = 0; i < valuesLines.size(); ++i )
208  {
209  const QStringList values = valuesLines[i].split( ',', QString::SkipEmptyParts );
210  QgsMeshDatasetValue point;
211 
212  if ( dataset.isScalar )
213  {
214  if ( values.size() != 1 )
215  {
216  setError( QgsError( tr( "Invalid dataset definition, dataset scalar values must be x" ),
217  QStringLiteral( "Mesh Memory Provider" ) ) );
218  return false;
219  }
220  else
221  {
222  point.setX( values[0].toDouble() );
223  }
224  }
225  else
226  {
227  if ( values.size() < 2 )
228  {
229  setError( QgsError( tr( "Invalid dataset definition, dataset vector values must be x, y" ),
230  QStringLiteral( "Mesh Memory Provider" ) ) );
231  return false;
232  }
233  else
234  {
235  point.setX( values[0].toDouble() );
236  point.setY( values[1].toDouble() );
237  }
238  }
239 
240  dataset.values.push_back( point );
241  }
242  return true;
243 }
244 
245 bool QgsMeshMemoryDataProvider::checkDatasetValidity( QgsMeshMemoryDataset &dataset )
246 {
247  bool valid = true;
248 
249  if ( dataset.isOnVertices )
250  {
251  if ( dataset.values.count() != vertexCount() )
252  {
253  valid = false;
254  setError( QgsError( tr( "Dataset defined on vertices has {} values, but mesh {}" ).arg( dataset.values.count(), vertexCount() ),
255  QStringLiteral( "Mesh Memory Provider" ) ) );
256  }
257  }
258  else
259  {
260  // on faces
261  if ( dataset.values.count() != faceCount() )
262  {
263  valid = false;
264  setError( QgsError( tr( "Dataset defined on faces has {} values, but mesh {}" ).arg( dataset.values.count(), faceCount() ),
265  QStringLiteral( "Mesh Memory Provider" ) ) );
266  }
267  }
268 
269  return valid;
270 }
271 
272 int QgsMeshMemoryDataProvider::vertexCount() const
273 {
274  return mVertices.size();
275 }
276 
277 int QgsMeshMemoryDataProvider::faceCount() const
278 {
279  return mFaces.size();
280 }
281 
282 QgsMeshVertex QgsMeshMemoryDataProvider::vertex( int index ) const
283 {
284  Q_ASSERT( vertexCount() > index );
285  return mVertices[index];
286 }
287 
288 QgsMeshFace QgsMeshMemoryDataProvider::face( int index ) const
289 {
290  Q_ASSERT( faceCount() > index );
291  return mFaces[index];
292 }
293 
294 bool QgsMeshMemoryDataProvider::addDataset( const QString &uri )
295 {
296  QgsMeshMemoryDataset ds;
297 
298  if ( mIsValid )
299  {
300  ds.valid = splitDatasetSections( uri, ds );
301  }
302  else
303  {
304  setError( QgsError( tr( "Unable to add dataset to invalid mesh" ),
305  QStringLiteral( "Mesh Memory Provider" ) ) );
306  }
307 
308  mDatasets.push_back( ds );
309 
310  return ds.valid;
311 }
312 
313 int QgsMeshMemoryDataProvider::datasetCount() const
314 {
315  return mDatasets.count();
316 }
317 
318 QgsMeshDatasetMetadata QgsMeshMemoryDataProvider::datasetMetadata( int index ) const
319 {
320  if ( ( index >= 0 ) && ( index < datasetCount() ) )
321  {
322  QgsMeshDatasetMetadata metadata(
323  mDatasets[index].isScalar,
324  mDatasets[index].valid,
325  mDatasets[index].isOnVertices,
326  mDatasets[index].metadata
327  );
328  return metadata;
329  }
330  else
331  {
332  return QgsMeshDatasetMetadata();
333  }
334 }
335 
336 QgsMeshDatasetValue QgsMeshMemoryDataProvider::datasetValue( int datasetIndex, int valueIndex ) const
337 {
338  if ( ( datasetIndex >= 0 ) &&
339  ( datasetIndex < datasetCount() ) &&
340  ( valueIndex >= 0 ) &&
341  ( valueIndex < mDatasets[datasetIndex].values.count() ) )
342  {
343  return mDatasets[datasetIndex].values[valueIndex];
344  }
345  else
346  {
347  return QgsMeshDatasetValue();
348  }
349 }
350 
351 
void setY(double y)
Sets Y value.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
Base class for providing data for QgsMeshLayer.
QgsError is container for error messages (report).
Definition: qgserror.h:80
QVector< int > QgsMeshFace
List of vertex indexes.
This class represents a coordinate reference system (CRS).
QgsMeshDatasetValue represents single mesh dataset value.
QgsMeshDatasetMetadata is a collection of mesh dataset metadata such as whether the data is vector or...
void setX(double x)
Sets X value.