Skip to content
Permalink
Browse files

Merge pull request #7008 from PeterPetrik/qgsmeshlayer_2_scalar_vecto…

…r_datasets

[mesh] Rendering of scalar and vector datasets
  • Loading branch information
wonder-sk committed May 24, 2018
2 parents dde895d + 882d8ed commit 61f84ce7f6d59fb472cd33299a51ec32584fcb36
Showing with 4,419 additions and 196 deletions.
  1. +70 −1 external/mdal/api/mdal.h
  2. +44 −41 external/mdal/frmts/mdal_2dm.cpp
  3. +2 −1 external/mdal/frmts/mdal_2dm.hpp
  4. +305 −0 external/mdal/frmts/mdal_ascii_dat.cpp
  5. +52 −0 external/mdal/frmts/mdal_ascii_dat.hpp
  6. +307 −0 external/mdal/frmts/mdal_binary_dat.cpp
  7. +46 −0 external/mdal/frmts/mdal_binary_dat.hpp
  8. +315 −26 external/mdal/mdal.cpp
  9. +96 −1 external/mdal/mdal_defines.hpp
  10. +15 −1 external/mdal/mdal_loader.cpp
  11. +4 −1 external/mdal/mdal_loader.hpp
  12. +41 −1 external/mdal/mdal_utils.cpp
  13. +30 −0 external/mdal/mdal_utils.hpp
  14. +203 −12 python/core/auto_generated/mesh/qgsmeshdataprovider.sip.in
  15. +61 −8 python/core/auto_generated/mesh/qgsmeshlayer.sip.in
  16. +292 −0 python/core/auto_generated/mesh/qgsmeshrenderersettings.sip.in
  17. +1 −0 python/core/core_auto.sip
  18. +6 −0 src/core/CMakeLists.txt
  19. +108 −0 src/core/mesh/qgsmeshdataprovider.cpp
  20. +186 −18 src/core/mesh/qgsmeshdataprovider.h
  21. +67 −18 src/core/mesh/qgsmeshlayer.cpp
  22. +56 −16 src/core/mesh/qgsmeshlayer.h
  23. +218 −0 src/core/mesh/qgsmeshlayerinterpolator.cpp
  24. +72 −0 src/core/mesh/qgsmeshlayerinterpolator.h
  25. +159 −5 src/core/mesh/qgsmeshlayerrenderer.cpp
  26. +45 −2 src/core/mesh/qgsmeshlayerrenderer.h
  27. +198 −11 src/core/mesh/qgsmeshmemorydataprovider.cpp
  28. +48 −3 src/core/mesh/qgsmeshmemorydataprovider.h
  29. +198 −0 src/core/mesh/qgsmeshrenderersettings.cpp
  30. +272 −0 src/core/mesh/qgsmeshrenderersettings.h
  31. +278 −0 src/core/mesh/qgsmeshvectorrenderer.cpp
  32. +103 −0 src/core/mesh/qgsmeshvectorrenderer.h
  33. +69 −0 src/core/mesh/qgstriangularmesh.cpp
  34. +13 −4 src/core/mesh/qgstriangularmesh.h
  35. +4 −0 src/providers/mdal/CMakeLists.txt
  36. +1 −1 src/providers/mdal/qgsmdaldataitems.h
  37. +87 −0 src/providers/mdal/qgsmdalprovider.cpp
  38. +9 −0 src/providers/mdal/qgsmdalprovider.h
  39. +163 −13 tests/src/core/testqgsmeshlayer.cpp
  40. +87 −12 tests/src/core/testqgsmeshlayerrenderer.cpp
  41. BIN ...expected_quad_and_triangle_face_scalar_dataset/expected_quad_and_triangle_face_scalar_dataset.png
  42. BIN ...expected_quad_and_triangle_face_vector_dataset/expected_quad_and_triangle_face_vector_dataset.png
  43. BIN ...es/mesh/expected_quad_and_triangle_triangular_mesh/expected_quad_and_triangle_triangular_mesh.png
  44. BIN ...cted_quad_and_triangle_vertex_scalar_dataset/expected_quad_and_triangle_vertex_scalar_dataset.png
  45. BIN ...cted_quad_and_triangle_vertex_vector_dataset/expected_quad_and_triangle_vertex_vector_dataset.png
  46. +12 −0 tests/testdata/mesh/quad_and_triangle_els_face_scalar.dat
  47. +12 −0 tests/testdata/mesh/quad_and_triangle_els_face_vector.dat
  48. +7 −0 tests/testdata/mesh/quad_and_triangle_face_scalar.txt
  49. +7 −0 tests/testdata/mesh/quad_and_triangle_face_vector.txt
  50. +15 −0 tests/testdata/mesh/quad_and_triangle_vertex_scalar.dat
  51. +10 −0 tests/testdata/mesh/quad_and_triangle_vertex_scalar.txt
  52. +15 −0 tests/testdata/mesh/quad_and_triangle_vertex_vector.dat
  53. +10 −0 tests/testdata/mesh/quad_and_triangle_vertex_vector.txt
@@ -6,6 +6,12 @@
#ifndef MDAL_H
#define MDAL_H

/**********************************************************************/
/**********************************************************************/
/* API is considered EXPERIMENTAL and can be changed without a notice */
/**********************************************************************/
/**********************************************************************/

#ifdef MDAL_STATIC
# define MDAL_EXPORT
#else
@@ -46,6 +52,7 @@ enum MDAL_Status
Err_UnknownFormat,
Err_IncompatibleMesh,
Err_InvalidData,
Err_IncompatibleDataset,
Err_MissingDriver,
// Warnings
Warn_UnsupportedElement,
@@ -57,6 +64,7 @@ enum MDAL_Status

//! Mesh
typedef void *MeshH;
typedef void *DatasetH;

//! Return MDAL version
MDAL_EXPORT const char *MDAL_Version();
@@ -68,7 +76,6 @@ MDAL_EXPORT MDAL_Status MDAL_LastStatus();
MDAL_EXPORT MeshH MDAL_LoadMesh( const char *meshFile );
//! Close mesh, free the memory
MDAL_EXPORT void MDAL_CloseMesh( MeshH mesh );

//! Return vertex count for the mesh
MDAL_EXPORT int MDAL_M_vertexCount( MeshH mesh );
//! Return vertex X coord for the mesh
@@ -82,6 +89,68 @@ MDAL_EXPORT int MDAL_M_faceVerticesCountAt( MeshH mesh, int index );
//! Return vertex index for face
MDAL_EXPORT int MDAL_M_faceVerticesIndexAt( MeshH mesh, int face_index, int vertex_index );

/**
* Load dataset file. On error see MDAL_LastStatus for error type.
* This may effectively load whole dataset in-memory for some providers
* Datasets will be closed automatically on mesh destruction or memory
* can be freed manually with MDAL_CloseDataset if needed
*/
MDAL_EXPORT void MDAL_M_LoadDatasets( MeshH mesh, const char *datasetFile );

//! Free the memory used to get dataset values
MDAL_EXPORT void MDAL_M_CloseDataset( DatasetH dataset );

//! Return dataset count
MDAL_EXPORT int MDAL_M_datasetCount( MeshH mesh );

//! Return dataset handle
MDAL_EXPORT DatasetH MDAL_M_dataset( MeshH mesh, int index );

//! Whether dataset has scalar data associated
MDAL_EXPORT bool MDAL_D_hasScalarData( DatasetH dataset );

//! Whether dataset is on vertices
MDAL_EXPORT bool MDAL_D_isOnVertices( DatasetH dataset );

//! Return number of metadata values
MDAL_EXPORT int MDAL_D_metadataCount( DatasetH dataset );

//! Return dataset metadata key
MDAL_EXPORT const char *MDAL_D_metadataKey( DatasetH dataset, int index );

//! Return dataset metadata value
MDAL_EXPORT const char *MDAL_D_metadataValue( DatasetH dataset, int index );

//! Return number of values
MDAL_EXPORT int MDAL_D_valueCount( DatasetH dataset );

/**
* Return scalar value associated with the index from the dataset
* for nodata return numeric_limits<double>:quiet_NaN
*/
MDAL_EXPORT double MDAL_D_value( DatasetH dataset, int valueIndex );

/**
* Return X value associated with the index from the vector dataset
* for nodata return numeric_limits<double>:quiet_NaN
*/
MDAL_EXPORT double MDAL_D_valueX( DatasetH dataset, int valueIndex );

/**
* Return Y value associated with the index from the vector dataset
* for nodata return numeric_limits<double>:quiet_NaN
*/
MDAL_EXPORT double MDAL_D_valueY( DatasetH dataset, int valueIndex );

/**
* Whether element is active - should be taken into account
* Some formats support switching off the element for particular timestep
*/
MDAL_EXPORT bool MDAL_D_active( DatasetH dataset, int faceIndex );

//! Return whether dataset is valid
MDAL_EXPORT bool MDAL_D_isValid( DatasetH dataset );

#ifdef __cplusplus
}
#endif
@@ -1,6 +1,6 @@
/*
MDAL - Mesh Data Abstraction Library (MIT License)
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
Copyright (C) 2018 Lutra Consulting Ltd.
*/

#include <stddef.h>
@@ -22,38 +22,38 @@ MDAL::Loader2dm::Loader2dm( const std::string &meshFile ):
{
}

MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
std::unique_ptr<MDAL::Mesh> MDAL::Loader2dm::load( MDAL_Status *status )
{
if ( status ) *status = MDAL_Status::None;

if ( !MDAL::fileExists( mMeshFile ) )
{
if ( status ) *status = MDAL_Status::Err_FileNotFound;
return 0;
return nullptr;
}

std::ifstream in( mMeshFile, std::ifstream::in );
std::string line;
if ( !std::getline( in, line ) || !startsWith( line, "MESH2D" ) )
{
if ( status ) *status = MDAL_Status::Err_UnknownFormat;
return 0;
return nullptr;
}

size_t elemCount = 0;
size_t nodeCount = 0;
size_t faceCount = 0;
size_t vertexCount = 0;

// Find out how many nodes and elements are contained in the .2dm mesh file
while ( std::getline( in, line ) )
{
if ( startsWith( line, "E4Q" ) ||
startsWith( line, "E3T" ) )
{
elemCount++;
faceCount++;
}
else if ( startsWith( line, "ND" ) )
{
nodeCount++;
vertexCount++;
}
else if ( startsWith( line, "E2L" ) ||
startsWith( line, "E3L" ) ||
@@ -62,71 +62,71 @@ MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
startsWith( line, "E9Q" ) )
{
if ( status ) *status = MDAL_Status::Warn_UnsupportedElement;
elemCount += 1; // We still count them as elements
faceCount += 1; // We still count them as elements
}
}

// Allocate memory
std::vector<Vertex> vertices( nodeCount );
std::vector<Face> faces( elemCount );
std::vector<Vertex> vertices( vertexCount );
std::vector<Face> faces( faceCount );

in.clear();
in.seekg( 0, std::ios::beg );

std::vector<std::string> chunks;

size_t elemIndex = 0;
size_t nodeIndex = 0;
std::map<size_t, size_t> elemIDtoIndex;
std::map<size_t, size_t> nodeIDtoIndex;
size_t faceIndex = 0;
size_t vertexIndex = 0;
std::map<size_t, size_t> faceIDtoIndex;
std::map<size_t, size_t> vertexIDtoIndex;

while ( std::getline( in, line ) )
{
if ( startsWith( line, "E4Q" ) )
{
chunks = split( line, " ", SplitBehaviour::SkipEmptyParts );
assert( elemIndex < elemCount );
assert( faceIndex < faceCount );

size_t elemID = toSizeT( chunks[1] );

std::map<size_t, size_t>::iterator search = elemIDtoIndex.find( elemID );
if ( search != elemIDtoIndex.end() )
std::map<size_t, size_t>::iterator search = faceIDtoIndex.find( elemID );
if ( search != faceIDtoIndex.end() )
{
if ( status ) *status = MDAL_Status::Warn_ElementNotUnique;
continue;
}
elemIDtoIndex[elemID] = elemIndex;
Face &face = faces[elemIndex];
faceIDtoIndex[elemID] = faceIndex;
Face &face = faces[faceIndex];
face.resize( 4 );
// Right now we just store node IDs here - we will convert them to node indices afterwards
for ( size_t i = 0; i < 4; ++i )
face[i] = toSizeT( chunks[i + 2] );

elemIndex++;
faceIndex++;
}
else if ( startsWith( line, "E3T" ) )
{
chunks = split( line, " ", SplitBehaviour::SkipEmptyParts );
assert( elemIndex < elemCount );
assert( faceIndex < faceCount );

size_t elemID = toSizeT( chunks[1] );

std::map<size_t, size_t>::iterator search = elemIDtoIndex.find( elemID );
if ( search != elemIDtoIndex.end() )
std::map<size_t, size_t>::iterator search = faceIDtoIndex.find( elemID );
if ( search != faceIDtoIndex.end() )
{
if ( status ) *status = MDAL_Status::Warn_ElementNotUnique;
continue;
}
elemIDtoIndex[elemID] = elemIndex;
Face &face = faces[elemIndex];
faceIDtoIndex[elemID] = faceIndex;
Face &face = faces[faceIndex];
face.resize( 3 );
// Right now we just store node IDs here - we will convert them to node indices afterwards
for ( size_t i = 0; i < 3; ++i )
{
face[i] = toSizeT( chunks[i + 2] );
}

elemIndex++;
faceIndex++;
}
else if ( startsWith( line, "E2L" ) ||
startsWith( line, "E3L" ) ||
@@ -136,39 +136,39 @@ MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
{
// We do not yet support these elements
chunks = split( line, " ", SplitBehaviour::SkipEmptyParts );
assert( elemIndex < elemCount );
assert( faceIndex < faceCount );

size_t elemID = toSizeT( chunks[1] );

std::map<size_t, size_t>::iterator search = elemIDtoIndex.find( elemID );
if ( search != elemIDtoIndex.end() )
std::map<size_t, size_t>::iterator search = faceIDtoIndex.find( elemID );
if ( search != faceIDtoIndex.end() )
{
if ( status ) *status = MDAL_Status::Warn_ElementNotUnique;
continue;
}
elemIDtoIndex[elemID] = elemIndex;
faceIDtoIndex[elemID] = faceIndex;
assert( false ); //TODO mark element as unusable

elemIndex++;
faceIndex++;
}
else if ( startsWith( line, "ND" ) )
{
chunks = split( line, " ", SplitBehaviour::SkipEmptyParts );
size_t nodeID = toSizeT( chunks[1] );

std::map<size_t, size_t>::iterator search = nodeIDtoIndex.find( nodeID );
if ( search != nodeIDtoIndex.end() )
std::map<size_t, size_t>::iterator search = vertexIDtoIndex.find( nodeID );
if ( search != vertexIDtoIndex.end() )
{
if ( status ) *status = MDAL_Status::Warn_NodeNotUnique;
continue;
}
nodeIDtoIndex[nodeID] = nodeIndex;
assert( nodeIndex < nodeCount );
Vertex &vertex = vertices[nodeIndex];
vertexIDtoIndex[nodeID] = vertexIndex;
assert( vertexIndex < vertexCount );
Vertex &vertex = vertices[vertexIndex];
vertex.x = toDouble( chunks[2] );
vertex.y = toDouble( chunks[3] );

nodeIndex++;
vertexIndex++;
}
}

@@ -179,8 +179,8 @@ MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
{
size_t nodeID = face[nd];

std::map<size_t, size_t>::iterator ni2i = nodeIDtoIndex.find( nodeID );
if ( ni2i != nodeIDtoIndex.end() )
std::map<size_t, size_t>::iterator ni2i = vertexIDtoIndex.find( nodeID );
if ( ni2i != vertexIDtoIndex.end() )
{
face[nd] = ni2i->second; // convert from ID to index
}
@@ -196,9 +196,12 @@ MDAL::Mesh *MDAL::Loader2dm::load( MDAL_Status *status )
//check that we have distinct nodes
}

Mesh *mesh = new Mesh;
std::unique_ptr< Mesh > mesh( new Mesh );
mesh->uri = mMeshFile;
mesh->faces = faces;
mesh->vertices = vertices;
mesh->faceIDtoIndex = faceIDtoIndex;
mesh->vertexIDtoIndex = vertexIDtoIndex;

return mesh;
}
@@ -7,6 +7,7 @@
#define MDAL_2DM_HPP

#include <string>
#include <memory>

#include "mdal_defines.hpp"
#include "mdal.h"
@@ -18,7 +19,7 @@ namespace MDAL
{
public:
Loader2dm( const std::string &meshFile );
Mesh *load( MDAL_Status *status );
std::unique_ptr< Mesh > load( MDAL_Status *status );

private:
std::string mMeshFile;

0 comments on commit 61f84ce

Please sign in to comment.
You can’t perform that action at this time.