24 static const QString TEXT_PROVIDER_KEY = QStringLiteral(
"mesh_memory" );
25 static const QString TEXT_PROVIDER_DESCRIPTION = QStringLiteral(
"Mesh memory provider" );
27 bool QgsMeshMemoryDataProvider::isValid()
const 32 QString QgsMeshMemoryDataProvider::name()
const 34 return TEXT_PROVIDER_KEY;
37 QString QgsMeshMemoryDataProvider::description()
const 39 return TEXT_PROVIDER_DESCRIPTION;
47 QgsMeshMemoryDataProvider::QgsMeshMemoryDataProvider(
const QString &uri,
const ProviderOptions &options )
50 mIsValid = splitMeshSections( uri );
53 QString QgsMeshMemoryDataProvider::providerKey()
55 return TEXT_PROVIDER_KEY;
58 QString QgsMeshMemoryDataProvider::providerDescription()
60 return TEXT_PROVIDER_DESCRIPTION;
63 QgsMeshMemoryDataProvider *QgsMeshMemoryDataProvider::createProvider(
const QString &uri,
const ProviderOptions &options )
65 return new QgsMeshMemoryDataProvider( uri, options );
68 bool QgsMeshMemoryDataProvider::splitMeshSections(
const QString &uri )
70 const QStringList sections = uri.split( QStringLiteral(
"---" ), QString::SkipEmptyParts );
71 if ( sections.size() != 2 )
73 setError(
QgsError( tr(
"Invalid mesh definition, does not contain 2 sections" ),
74 QStringLiteral(
"Mesh Memory Provider" ) ) );
78 if ( addMeshVertices( sections[0] ) )
79 return addMeshFaces( sections[1] );
84 bool QgsMeshMemoryDataProvider::addMeshVertices(
const QString &def )
86 QVector<QgsMeshVertex> vertices;
88 const QStringList verticesCoords = def.split(
'\n', QString::SkipEmptyParts );
89 for (
int i = 0; i < verticesCoords.size(); ++i )
91 const QStringList coords = verticesCoords[i].split(
',', QString::SkipEmptyParts );
92 if ( coords.size() != 2 )
94 setError(
QgsError( tr(
"Invalid mesh definition, vertex definition does not contain x, y" ),
95 QStringLiteral(
"Mesh Memory Provider" ) ) );
98 double x = coords.at( 0 ).toDouble();
99 double y = coords.at( 1 ).toDouble();
101 vertices.push_back( vertex );
104 mVertices = vertices;
108 bool QgsMeshMemoryDataProvider::addMeshFaces(
const QString &def )
110 QVector<QgsMeshFace> faces;
112 const QStringList facesVertices = def.split(
'\n', QString::SkipEmptyParts );
113 for (
int i = 0; i < facesVertices.size(); ++i )
115 const QStringList vertices = facesVertices[i].split(
',', QString::SkipEmptyParts );
116 if ( vertices.size() < 3 )
118 setError(
QgsError( tr(
"Invalid mesh definition, face must contain at least 3 vertices" ),
119 QStringLiteral(
"Mesh Memory Provider" ) ) );
123 for (
int j = 0; j < vertices.size(); ++j )
125 int vertex_id = vertices[j].toInt();
128 setError(
QgsError( tr(
"Invalid mesh definition, vertex index must be positive value" ),
129 QStringLiteral(
"Mesh Memory Provider" ) ) );
132 if ( mVertices.size() < vertex_id )
134 setError(
QgsError( tr(
"Invalid mesh definition, missing vertex id defined in face" ),
135 QStringLiteral(
"Mesh Memory Provider" ) ) );
139 face.push_back( vertex_id );
141 faces.push_back( face );
149 bool QgsMeshMemoryDataProvider::splitDatasetSections(
const QString &uri, QgsMeshMemoryDatasetGroup &datasetGroup )
151 const QStringList sections = uri.split( QStringLiteral(
"---" ), QString::SkipEmptyParts );
153 bool success = sections.size() > 2;
156 setError(
QgsError( tr(
"Invalid dataset definition, does not contain 3+ sections" ),
157 QStringLiteral(
"Mesh Memory Provider" ) ) );
161 success = setDatasetGroupType( sections[0], datasetGroup );
163 success = addDatasetGroupMetadata( sections[1], datasetGroup );
165 for (
int i = 2; i < sections.size(); ++i )
169 std::shared_ptr<QgsMeshMemoryDataset> dataset = std::make_shared<QgsMeshMemoryDataset>();
170 success = addDatasetValues( sections[i], dataset, datasetGroup.isScalar );
174 datasetGroup.datasets.push_back( dataset );
180 bool QgsMeshMemoryDataProvider::setDatasetGroupType(
const QString &def, QgsMeshMemoryDatasetGroup &datasetGroup )
182 const QStringList types = def.split(
' ', QString::SkipEmptyParts );
184 if ( types.size() != 3 )
186 setError(
QgsError( tr(
"Invalid type definition, must be Vertex/Face Vector/Scalar Name" ),
187 QStringLiteral(
"Mesh Memory Provider" ) ) );
191 if ( 0 == QString::compare( types[0].trimmed(), QStringLiteral(
"vertex" ), Qt::CaseInsensitive ) )
196 datasetGroup.isScalar = 0 == QString::compare( types[1].trimmed(), QStringLiteral(
"scalar" ), Qt::CaseInsensitive );
197 datasetGroup.name = types[2].trimmed();
202 bool QgsMeshMemoryDataProvider::addDatasetGroupMetadata(
const QString &def, QgsMeshMemoryDatasetGroup &datasetGroup )
204 const QStringList metadataLines = def.split(
'\n', QString::SkipEmptyParts );
205 for (
int i = 0; i < metadataLines.size(); ++i )
207 const QStringList keyVal = metadataLines[i].split(
':', QString::SkipEmptyParts );
208 if ( keyVal.size() != 2 )
210 setError(
QgsError( tr(
"Invalid dataset definition, dataset metadata does not contain key: value" ),
211 QStringLiteral(
"Mesh Memory Provider" ) ) );
215 datasetGroup.metadata.insert( keyVal.at( 0 ).trimmed(), keyVal.at( 1 ).trimmed() );
220 bool QgsMeshMemoryDataProvider::addDatasetValues(
const QString &def, std::shared_ptr<QgsMeshMemoryDataset> &dataset,
bool isScalar )
222 const QStringList valuesLines = def.split(
'\n', QString::SkipEmptyParts );
224 if ( valuesLines.size() < 2 )
226 setError(
QgsError( tr(
"Invalid dataset definition, must contain at least 1 line (time)" ),
227 QStringLiteral(
"Mesh Memory Provider" ) ) );
231 dataset->time = valuesLines[0].toDouble();
233 for (
int i = 1; i < valuesLines.size(); ++i )
235 const QStringList values = valuesLines[i].split(
',', QString::SkipEmptyParts );
240 if ( values.size() != 1 )
242 setError(
QgsError( tr(
"Invalid dataset definition, dataset scalar values must be x" ),
243 QStringLiteral(
"Mesh Memory Provider" ) ) );
248 point.
setX( values[0].toDouble() );
253 if ( values.size() < 2 )
255 setError(
QgsError( tr(
"Invalid dataset definition, dataset vector values must be x, y" ),
256 QStringLiteral(
"Mesh Memory Provider" ) ) );
261 point.
setX( values[0].toDouble() );
262 point.
setY( values[1].toDouble() );
266 dataset->values.push_back( point );
271 bool QgsMeshMemoryDataProvider::checkDatasetValidity( std::shared_ptr<QgsMeshMemoryDataset> &dataset,
bool isOnVertices )
277 if ( dataset->values.count() != vertexCount() )
280 setError(
QgsError( tr(
"Dataset defined on vertices has {} values, but mesh {}" ).arg( dataset->values.count(), vertexCount() ),
281 QStringLiteral(
"Mesh Memory Provider" ) ) );
287 if ( dataset->values.count() != faceCount() )
290 setError(
QgsError( tr(
"Dataset defined on faces has {} values, but mesh {}" ).arg( dataset->values.count(), faceCount() ),
291 QStringLiteral(
"Mesh Memory Provider" ) ) );
295 dataset->valid = valid;
299 int QgsMeshMemoryDataProvider::vertexCount()
const 301 return mVertices.size();
304 int QgsMeshMemoryDataProvider::faceCount()
const 306 return mFaces.size();
309 void QgsMeshMemoryDataProvider::populateMesh(
QgsMesh *mesh )
const 313 mesh->
faces = mFaces;
320 return calculateExtent( );
323 bool QgsMeshMemoryDataProvider::addDataset(
const QString &uri )
325 QgsMeshMemoryDatasetGroup group;
330 valid = splitDatasetSections( uri, group );
334 setError(
QgsError( tr(
"Unable to add dataset group to invalid mesh" ),
335 QStringLiteral(
"Mesh Memory Provider" ) ) );
338 calculateMinMaxForDatasetGroup( group );
339 mDatasetGroups.push_back( group );
343 mExtraDatasetUris << uri;
344 emit datasetGroupsAdded( 1 );
351 QStringList QgsMeshMemoryDataProvider::extraDatasets()
const 353 return mExtraDatasetUris;
356 int QgsMeshMemoryDataProvider::datasetGroupCount()
const 358 return mDatasetGroups.count();
361 int QgsMeshMemoryDataProvider::datasetCount(
int groupIndex )
const 363 if ( ( groupIndex >= 0 ) && ( groupIndex < datasetGroupCount() ) )
364 return mDatasetGroups[groupIndex].datasets.count();
371 if ( ( groupIndex >= 0 ) && ( groupIndex < datasetGroupCount() ) )
373 return mDatasetGroups[groupIndex].groupMetadata();
393 int QgsMeshMemoryDatasetGroup::datasetCount()
const 395 return datasets.size();
398 void QgsMeshMemoryDatasetGroup::addDataset( std::shared_ptr<QgsMeshMemoryDataset> dataset )
400 datasets.push_back( dataset );
403 void QgsMeshMemoryDatasetGroup::clearDatasets()
408 std::shared_ptr<const QgsMeshMemoryDataset> QgsMeshMemoryDatasetGroup::constDataset(
int index )
const 410 return datasets[index];
415 if ( ( index.
group() >= 0 ) && ( index.
group() < datasetGroupCount() ) &&
419 const QgsMeshMemoryDatasetGroup &grp = mDatasetGroups.at( index.
group() );
421 grp.datasets[index.
dataset()]->time,
422 grp.datasets[index.
dataset()]->valid,
423 grp.datasets[index.
dataset()]->minimum,
424 grp.datasets[index.
dataset()]->maximum
436 if ( ( index.
group() >= 0 ) && ( index.
group() < datasetGroupCount() ) &&
438 ( valueIndex >= 0 ) && ( valueIndex < mDatasetGroups[index.
group()].datasets[index.
dataset()]->values.count() ) )
440 return mDatasetGroups[index.
group()].datasets[index.
dataset()]->values[valueIndex];
450 if ( ( index.
group() >= 0 ) && ( index.
group() < datasetGroupCount() ) )
452 const QgsMeshMemoryDatasetGroup group = mDatasetGroups[index.
group()];
453 bool isScalar = group.isScalar;
454 if ( ( index.
dataset() >= 0 ) && ( index.
dataset() < group.datasets.size() ) )
456 return group.datasets[index.
dataset()]->datasetValues( isScalar, valueIndex, count );
469 QgsMeshDataBlock QgsMeshMemoryDataset::datasetValues(
bool isScalar,
int valueIndex,
int count )
const 472 double *buf =
static_cast<double *
>( ret.buffer() );
474 for (
int i = 0; i < count; ++i )
476 int idx = valueIndex + i;
477 if ( ( idx < 0 ) || ( idx >= values.size() ) )
485 buf[2 * i] = val.
x();
486 buf[2 * i + 1] = val.
y();
492 bool QgsMeshMemoryDataProvider::isFaceActive(
QgsMeshDatasetIndex index,
int faceIndex )
const 494 if ( mDatasetGroups[index.
group()].datasets[index.
dataset()]->active.isEmpty() )
497 return mDatasetGroups[index.
group()].datasets[index.
dataset()]->active[faceIndex];
502 if ( ( index.
group() >= 0 ) && ( index.
group() < datasetGroupCount() ) )
504 const QgsMeshMemoryDatasetGroup group = mDatasetGroups[index.
group()];
505 if ( ( index.
dataset() >= 0 ) && ( index.
dataset() < group.datasets.size() ) )
507 return group.datasets[index.
dataset()]->areFacesActive( faceIndex, count );
520 QgsMeshDataBlock QgsMeshMemoryDataset::areFacesActive(
int faceIndex,
int count )
const 523 if ( active.isEmpty() ||
525 ( faceIndex + count > active.size() )
527 memset( ret.buffer(), 1,
static_cast<size_t>( count ) *
sizeof(
int ) );
529 memcpy( ret.buffer(),
530 active.data() + faceIndex,
531 static_cast<size_t>( count ) *
sizeof(
int ) );
536 bool QgsMeshMemoryDataProvider::persistDatasetGroup(
const QString &path,
538 const QVector<QgsMeshDataBlock> &datasetValues,
539 const QVector<QgsMeshDataBlock> &datasetActive,
540 const QVector<double> × )
544 Q_UNUSED( datasetValues );
545 Q_UNUSED( datasetActive );
550 void QgsMeshMemoryDataProvider::calculateMinMaxForDatasetGroup( QgsMeshMemoryDatasetGroup &grp )
const 552 double min = std::numeric_limits<double>::max();
553 double max = std::numeric_limits<double>::min();
555 int count = grp.datasets.size();
556 for (
int i = 0; i < count; ++i )
558 calculateMinMaxForDataset( grp.datasets[i] );
559 min = std::min( min, grp.datasets[i]->minimum );
560 max = std::max( max, grp.datasets[i]->maximum );
567 void QgsMeshMemoryDataProvider::calculateMinMaxForDataset( std::shared_ptr<QgsMeshMemoryDataset> &dataset )
const 569 double min = std::numeric_limits<double>::max();
570 double max = std::numeric_limits<double>::min();
572 if ( !dataset->valid )
577 bool firstIteration =
true;
578 for (
int i = 0; i < dataset->values.size(); ++i )
580 double v = dataset->values[i].scalar();
582 if ( std::isnan( v ) )
584 if ( firstIteration )
586 firstIteration =
false;
603 dataset->minimum = min;
604 dataset->maximum = max;
607 QgsRectangle QgsMeshMemoryDataProvider::calculateExtent()
const 622 QgsMeshMemoryDatasetGroup::QgsMeshMemoryDatasetGroup(
const QString &nm ):
627 QgsMeshMemoryDatasetGroup::QgsMeshMemoryDatasetGroup() =
default;
628 QgsMeshMemoryDataset::QgsMeshMemoryDataset() =
default;
A rectangle specified with double values.
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
void setXMaximum(double x)
Set the maximum x value.
int dataset() const
Returns a dataset index within group()
Vector double pairs (x1, y1, x2, y2, ... )
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e...
void setY(double y)
Sets Y value.
const QgsCoordinateReferenceSystem & crs
int group() const
Returns a group index.
double y() const
Returns y value.
QVector< QgsMeshVertex > vertices
vertices
void setYMinimum(double y)
Set the minimum y value.
Integer boolean flag whether face is active.
Point geometry type, with support for z-dimension and m-values.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Base class for providing data for QgsMeshLayer.
Mesh - vertices and faces.
QgsError is container for error messages (report).
void setYMaximum(double y)
Set the maximum y value.
QVector< int > QgsMeshFace
List of vertex indexes.
This class represents a coordinate reference system (CRS).
QgsMeshDatasetIndex is index that identifies the dataset group (e.g.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
QVector< QgsMeshFace > faces
faces
QgsMeshDatasetValue represents single dataset value.
void setX(double x)
Sets X value.
double x() const
Returns x value.
void setXMinimum(double x)
Set the minimum x value.