mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Merge pull request #6820 from PeterPetrik/QgsMeshLayer_1_mesh
[FEATURE] QgsMeshLayer part 1: Reading raw mesh
This commit is contained in:
commit
ade216d02d
@ -95,6 +95,12 @@ IF(WITH_CORE)
|
|||||||
SET (HAVE_GUI TRUE) # used in qgsconfig.h
|
SET (HAVE_GUI TRUE) # used in qgsconfig.h
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
# try to configure and build MDAL support
|
||||||
|
SET (WITH_INTERNAL_MDAL TRUE CACHE BOOL "Determines whether MDAL support should be built")
|
||||||
|
IF (NOT WITH_INTERNAL_MDAL)
|
||||||
|
SET (MDAL_PREFIX "" CACHE PATH "Path to MDAL base directory")
|
||||||
|
ENDIF (NOT WITH_INTERNAL_MDAL)
|
||||||
|
|
||||||
# try to configure and build POSTGRESQL support
|
# try to configure and build POSTGRESQL support
|
||||||
SET (WITH_POSTGRESQL TRUE CACHE BOOL "Determines whether POSTGRESQL support should be built")
|
SET (WITH_POSTGRESQL TRUE CACHE BOOL "Determines whether POSTGRESQL support should be built")
|
||||||
IF (WITH_POSTGRESQL)
|
IF (WITH_POSTGRESQL)
|
||||||
@ -258,6 +264,10 @@ IF(WITH_CORE)
|
|||||||
FIND_PACKAGE(Postgres) # PostgreSQL provider
|
FIND_PACKAGE(Postgres) # PostgreSQL provider
|
||||||
ENDIF (WITH_POSTGRESQL)
|
ENDIF (WITH_POSTGRESQL)
|
||||||
|
|
||||||
|
IF (NOT WITH_INTERNAL_MDAL)
|
||||||
|
FIND_PACKAGE(MDAL REQUIRED) # MDAL provider
|
||||||
|
ENDIF (NOT WITH_INTERNAL_MDAL)
|
||||||
|
|
||||||
FIND_PACKAGE(SpatiaLite REQUIRED)
|
FIND_PACKAGE(SpatiaLite REQUIRED)
|
||||||
|
|
||||||
IF (NOT PROJ_FOUND OR NOT GEOS_FOUND OR NOT GDAL_FOUND)
|
IF (NOT PROJ_FOUND OR NOT GEOS_FOUND OR NOT GDAL_FOUND)
|
||||||
|
32
cmake/FindMDAL.cmake
Normal file
32
cmake/FindMDAL.cmake
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Find MDAL
|
||||||
|
# ~~~~~~~~~
|
||||||
|
# Copyright (c) 2018, Peter Petrik <zilolv at gmail dot com>
|
||||||
|
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||||
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Once run this will define:
|
||||||
|
# MDAL_FOUND - System has MDAL
|
||||||
|
# MDAL_INCLUDE_DIRS - The MDAL include directories
|
||||||
|
# MDAL_LIBRARIES - The libraries needed to use MDAL
|
||||||
|
# MDAL_DEFINITIONS - Compiler switches required for using MDAL
|
||||||
|
|
||||||
|
FIND_PACKAGE(PkgConfig)
|
||||||
|
PKG_CHECK_MODULES(PC_MDAL QUIET libmdal)
|
||||||
|
SET(MDAL_DEFINITIONS ${PC_MDAL_CFLAGS_OTHER})
|
||||||
|
|
||||||
|
FIND_PATH(MDAL_INCLUDE_DIR mdal.h
|
||||||
|
HINTS ${PC_MDAL_INCLUDEDIR} ${PC_MDAL_INCLUDE_DIRS} ${MDAL_PREFIX}/include
|
||||||
|
PATH_SUFFIXES libmdal )
|
||||||
|
|
||||||
|
FIND_LIBRARY(MDAL_LIBRARY NAMES mdal libmdal
|
||||||
|
HINTS ${PC_MDAL_LIBDIR} ${PC_MDAL_LIBRARY_DIRS} ${MDAL_PREFIX}/lib)
|
||||||
|
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MDAL DEFAULT_MSG
|
||||||
|
MDAL_LIBRARY MDAL_INCLUDE_DIR)
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(MDAL_INCLUDE_DIR MDAL_LIBRARY )
|
||||||
|
|
||||||
|
SET(MDAL_LIBRARIES ${MDAL_LIBRARY} )
|
||||||
|
SET(MDAL_INCLUDE_DIRS ${MDAL_INCLUDE_DIR} )
|
@ -70,6 +70,7 @@ IF(WITH_APIDOC)
|
|||||||
${CMAKE_SOURCE_DIR}/src/core/layout
|
${CMAKE_SOURCE_DIR}/src/core/layout
|
||||||
${CMAKE_SOURCE_DIR}/src/core/locator
|
${CMAKE_SOURCE_DIR}/src/core/locator
|
||||||
${CMAKE_SOURCE_DIR}/src/core/metadata
|
${CMAKE_SOURCE_DIR}/src/core/metadata
|
||||||
|
${CMAKE_SOURCE_DIR}/src/core/mesh
|
||||||
${CMAKE_SOURCE_DIR}/src/core/pal
|
${CMAKE_SOURCE_DIR}/src/core/pal
|
||||||
${CMAKE_SOURCE_DIR}/src/core/processing
|
${CMAKE_SOURCE_DIR}/src/core/processing
|
||||||
${CMAKE_SOURCE_DIR}/src/core/providers
|
${CMAKE_SOURCE_DIR}/src/core/providers
|
||||||
|
89
external/mdal/api/mdal.h
vendored
Normal file
89
external/mdal/api/mdal.h
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||||
|
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MDAL_H
|
||||||
|
#define MDAL_H
|
||||||
|
|
||||||
|
#ifdef MDAL_STATIC
|
||||||
|
# define MDAL_EXPORT
|
||||||
|
#else
|
||||||
|
# if defined _WIN32 || defined __CYGWIN__
|
||||||
|
# ifdef mdal_EXPORTS
|
||||||
|
# ifdef __GNUC__
|
||||||
|
# define MDAL_EXPORT __attribute__ ((dllexport))
|
||||||
|
# else
|
||||||
|
# define MDAL_EXPORT __declspec(dllexport) // Note: actually gcc seems to also supports this syntax.
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# ifdef __GNUC__
|
||||||
|
# define MDAL_EXPORT __attribute__ ((dllimport))
|
||||||
|
# else
|
||||||
|
# define MDAL_EXPORT __declspec(dllimport) // Note: actually gcc seems to also supports this syntax.
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# if __GNUC__ >= 4
|
||||||
|
# define MDAL_EXPORT __attribute__ ((visibility ("default")))
|
||||||
|
# else
|
||||||
|
# define MDAL_EXPORT
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Statuses */
|
||||||
|
enum MDAL_Status
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
// Errors
|
||||||
|
Err_NotEnoughMemory,
|
||||||
|
Err_FileNotFound,
|
||||||
|
Err_UnknownFormat,
|
||||||
|
Err_IncompatibleMesh,
|
||||||
|
Err_InvalidData,
|
||||||
|
Err_MissingDriver,
|
||||||
|
// Warnings
|
||||||
|
Warn_UnsupportedElement,
|
||||||
|
Warn_InvalidElements,
|
||||||
|
Warn_ElementWithInvalidNode,
|
||||||
|
Warn_ElementNotUnique,
|
||||||
|
Warn_NodeNotUnique
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Mesh
|
||||||
|
typedef void *MeshH;
|
||||||
|
|
||||||
|
//! Return MDAL version
|
||||||
|
MDAL_EXPORT const char *MDAL_Version();
|
||||||
|
|
||||||
|
//! Return last status message
|
||||||
|
MDAL_EXPORT MDAL_Status MDAL_LastStatus();
|
||||||
|
|
||||||
|
//! Load mesh file. On error see MDAL_LastStatus for error type This effectively loads whole mesh in-memory
|
||||||
|
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
|
||||||
|
MDAL_EXPORT double MDAL_M_vertexXCoordinatesAt( MeshH mesh, int index );
|
||||||
|
//! Return vertex Y coord for the mesh
|
||||||
|
MDAL_EXPORT double MDAL_M_vertexYCoordinatesAt( MeshH mesh, int index );
|
||||||
|
//! Return face count for the mesh
|
||||||
|
MDAL_EXPORT int MDAL_M_faceCount( MeshH mesh );
|
||||||
|
//! Return number of vertices face consist of, e.g. 3 for triangle
|
||||||
|
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 );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //MDAL_H
|
204
external/mdal/frmts/mdal_2dm.cpp
vendored
Normal file
204
external/mdal/frmts/mdal_2dm.cpp
vendored
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
/*
|
||||||
|
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||||
|
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "mdal_2dm.hpp"
|
||||||
|
#include "mdal.h"
|
||||||
|
#include "mdal_utils.hpp"
|
||||||
|
|
||||||
|
MDAL::Loader2dm::Loader2dm( const std::string &meshFile ):
|
||||||
|
mMeshFile( meshFile )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t elemCount = 0;
|
||||||
|
size_t nodeCount = 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++;
|
||||||
|
}
|
||||||
|
else if ( startsWith( line, "ND" ) )
|
||||||
|
{
|
||||||
|
nodeCount++;
|
||||||
|
}
|
||||||
|
else if ( startsWith( line, "E2L" ) ||
|
||||||
|
startsWith( line, "E3L" ) ||
|
||||||
|
startsWith( line, "E6T" ) ||
|
||||||
|
startsWith( line, "E8Q" ) ||
|
||||||
|
startsWith( line, "E9Q" ) )
|
||||||
|
{
|
||||||
|
if ( status ) *status = MDAL_Status::Warn_UnsupportedElement;
|
||||||
|
elemCount += 1; // We still count them as elements
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory
|
||||||
|
std::vector<Vertex> vertices( nodeCount );
|
||||||
|
std::vector<Face> faces( elemCount );
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
while ( std::getline( in, line ) )
|
||||||
|
{
|
||||||
|
if ( startsWith( line, "E4Q" ) )
|
||||||
|
{
|
||||||
|
chunks = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||||
|
assert( elemIndex < elemCount );
|
||||||
|
|
||||||
|
size_t elemID = toSizeT( chunks[1] );
|
||||||
|
|
||||||
|
std::map<size_t, size_t>::iterator search = elemIDtoIndex.find( elemID );
|
||||||
|
if ( search != elemIDtoIndex.end() )
|
||||||
|
{
|
||||||
|
if ( status ) *status = MDAL_Status::Warn_ElementNotUnique;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
elemIDtoIndex[elemID] = elemIndex;
|
||||||
|
Face &face = faces[elemIndex];
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
else if ( startsWith( line, "E3T" ) )
|
||||||
|
{
|
||||||
|
chunks = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||||
|
assert( elemIndex < elemCount );
|
||||||
|
|
||||||
|
size_t elemID = toSizeT( chunks[1] );
|
||||||
|
|
||||||
|
std::map<size_t, size_t>::iterator search = elemIDtoIndex.find( elemID );
|
||||||
|
if ( search != elemIDtoIndex.end() )
|
||||||
|
{
|
||||||
|
if ( status ) *status = MDAL_Status::Warn_ElementNotUnique;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
elemIDtoIndex[elemID] = elemIndex;
|
||||||
|
Face &face = faces[elemIndex];
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
else if ( startsWith( line, "E2L" ) ||
|
||||||
|
startsWith( line, "E3L" ) ||
|
||||||
|
startsWith( line, "E6T" ) ||
|
||||||
|
startsWith( line, "E8Q" ) ||
|
||||||
|
startsWith( line, "E9Q" ) )
|
||||||
|
{
|
||||||
|
// We do not yet support these elements
|
||||||
|
chunks = split( line, " ", SplitBehaviour::SkipEmptyParts );
|
||||||
|
assert( elemIndex < elemCount );
|
||||||
|
|
||||||
|
size_t elemID = toSizeT( chunks[1] );
|
||||||
|
|
||||||
|
std::map<size_t, size_t>::iterator search = elemIDtoIndex.find( elemID );
|
||||||
|
if ( search != elemIDtoIndex.end() )
|
||||||
|
{
|
||||||
|
if ( status ) *status = MDAL_Status::Warn_ElementNotUnique;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
elemIDtoIndex[elemID] = elemIndex;
|
||||||
|
assert( false ); //TODO mark element as unusable
|
||||||
|
|
||||||
|
elemIndex++;
|
||||||
|
}
|
||||||
|
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() )
|
||||||
|
{
|
||||||
|
if ( status ) *status = MDAL_Status::Warn_NodeNotUnique;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nodeIDtoIndex[nodeID] = nodeIndex;
|
||||||
|
assert( nodeIndex < nodeCount );
|
||||||
|
Vertex &vertex = vertices[nodeIndex];
|
||||||
|
vertex.x = toDouble( chunks[2] );
|
||||||
|
vertex.y = toDouble( chunks[3] );
|
||||||
|
|
||||||
|
nodeIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( std::vector<Face>::iterator it = faces.begin(); it != faces.end(); ++it )
|
||||||
|
{
|
||||||
|
Face &face = *it;
|
||||||
|
for ( Face::size_type nd = 0; nd < face.size(); ++nd )
|
||||||
|
{
|
||||||
|
size_t nodeID = face[nd];
|
||||||
|
|
||||||
|
std::map<size_t, size_t>::iterator ni2i = nodeIDtoIndex.find( nodeID );
|
||||||
|
if ( ni2i != nodeIDtoIndex.end() )
|
||||||
|
{
|
||||||
|
face[nd] = ni2i->second; // convert from ID to index
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert( false ); //TODO mark element as unusable
|
||||||
|
|
||||||
|
if ( status ) *status = MDAL_Status::Warn_ElementWithInvalidNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO check validity of the face
|
||||||
|
//check that we have distinct nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh *mesh = new Mesh;
|
||||||
|
mesh->faces = faces;
|
||||||
|
mesh->vertices = vertices;
|
||||||
|
|
||||||
|
return mesh;
|
||||||
|
}
|
28
external/mdal/frmts/mdal_2dm.hpp
vendored
Normal file
28
external/mdal/frmts/mdal_2dm.hpp
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||||
|
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MDAL_2DM_HPP
|
||||||
|
#define MDAL_2DM_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "mdal_defines.hpp"
|
||||||
|
#include "mdal.h"
|
||||||
|
|
||||||
|
namespace MDAL
|
||||||
|
{
|
||||||
|
|
||||||
|
class Loader2dm
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Loader2dm( const std::string &meshFile );
|
||||||
|
Mesh *load( MDAL_Status *status );
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string mMeshFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace MDAL
|
||||||
|
#endif //MDAL_2DM_HPP
|
100
external/mdal/mdal.cpp
vendored
Normal file
100
external/mdal/mdal.cpp
vendored
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <cassert>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "mdal.h"
|
||||||
|
#include "mdal_loader.hpp"
|
||||||
|
#include "mdal_defines.hpp"
|
||||||
|
|
||||||
|
static MDAL_Status sLastStatus;
|
||||||
|
|
||||||
|
const char *MDAL_Version()
|
||||||
|
{
|
||||||
|
return "0.0.2";
|
||||||
|
}
|
||||||
|
|
||||||
|
MDAL_Status MDAL_LastStatus()
|
||||||
|
{
|
||||||
|
return sLastStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshH MDAL_LoadMesh( const char *meshFile )
|
||||||
|
{
|
||||||
|
if ( !meshFile )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
std::string filename( meshFile );
|
||||||
|
return ( MeshH ) MDAL::Loader::load( filename, &sLastStatus );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MDAL_CloseMesh( MeshH mesh )
|
||||||
|
{
|
||||||
|
if ( mesh )
|
||||||
|
{
|
||||||
|
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||||
|
delete m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int MDAL_M_vertexCount( MeshH mesh )
|
||||||
|
{
|
||||||
|
assert( mesh );
|
||||||
|
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||||
|
int len = static_cast<int>( m->vertices.size() );
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
double MDAL_M_vertexXCoordinatesAt( MeshH mesh, int index )
|
||||||
|
{
|
||||||
|
assert( mesh );
|
||||||
|
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||||
|
assert( index > -1 );
|
||||||
|
size_t i = static_cast<size_t>( index );
|
||||||
|
assert( m->vertices.size() > i );
|
||||||
|
return m->vertices[i].x;
|
||||||
|
}
|
||||||
|
|
||||||
|
double MDAL_M_vertexYCoordinatesAt( MeshH mesh, int index )
|
||||||
|
{
|
||||||
|
assert( mesh );
|
||||||
|
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||||
|
assert( index > -1 );
|
||||||
|
size_t i = static_cast<size_t>( index );
|
||||||
|
assert( m->vertices.size() > i );
|
||||||
|
return m->vertices[i].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MDAL_M_faceCount( MeshH mesh )
|
||||||
|
{
|
||||||
|
assert( mesh );
|
||||||
|
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||||
|
int len = static_cast<int>( m->faces.size() );
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MDAL_M_faceVerticesCountAt( MeshH mesh, int index )
|
||||||
|
{
|
||||||
|
assert( mesh );
|
||||||
|
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||||
|
assert( index > -1 );
|
||||||
|
size_t i = static_cast<size_t>( index );
|
||||||
|
assert( m->faces.size() > i );
|
||||||
|
int len = static_cast<int>( m->faces[i].size() );
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MDAL_M_faceVerticesIndexAt( MeshH mesh, int face_index, int vertex_index )
|
||||||
|
{
|
||||||
|
assert( mesh );
|
||||||
|
MDAL::Mesh *m = ( MDAL::Mesh * ) mesh;
|
||||||
|
assert( face_index > -1 );
|
||||||
|
size_t fi = static_cast<size_t>( face_index );
|
||||||
|
assert( m->faces.size() > fi );
|
||||||
|
assert( vertex_index > -1 );
|
||||||
|
size_t vi = static_cast<size_t>( vertex_index );
|
||||||
|
assert( m->faces[fi].size() > vi );
|
||||||
|
int len = static_cast<int>( m->faces[fi][vi] );
|
||||||
|
return len;
|
||||||
|
}
|
31
external/mdal/mdal_defines.hpp
vendored
Normal file
31
external/mdal/mdal_defines.hpp
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||||
|
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MDAL_DEFINES_HPP
|
||||||
|
#define MDAL_DEFINES_HPP
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace MDAL
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
} Vertex;
|
||||||
|
|
||||||
|
typedef std::vector<size_t> Face;
|
||||||
|
|
||||||
|
struct Mesh
|
||||||
|
{
|
||||||
|
std::vector<Vertex> vertices;
|
||||||
|
std::vector<Face> faces;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace MDAL
|
||||||
|
#endif //MDAL_DEFINES_HPP
|
||||||
|
|
13
external/mdal/mdal_loader.cpp
vendored
Normal file
13
external/mdal/mdal_loader.cpp
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||||
|
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mdal_loader.hpp"
|
||||||
|
#include "frmts/mdal_2dm.hpp"
|
||||||
|
|
||||||
|
MDAL::Mesh *MDAL::Loader::load( const std::string &meshFile, MDAL_Status *status )
|
||||||
|
{
|
||||||
|
MDAL::Loader2dm loader( meshFile );
|
||||||
|
return loader.load( status );
|
||||||
|
}
|
24
external/mdal/mdal_loader.hpp
vendored
Normal file
24
external/mdal/mdal_loader.hpp
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||||
|
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MDAL_LOADER_HPP
|
||||||
|
#define MDAL_LOADER_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "mdal.h"
|
||||||
|
#include "mdal_defines.hpp"
|
||||||
|
|
||||||
|
namespace MDAL
|
||||||
|
{
|
||||||
|
|
||||||
|
class Loader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static Mesh *load( const std::string &meshFile, MDAL_Status *status );
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace MDAL
|
||||||
|
#endif //MDAL_LOADER_HPP
|
56
external/mdal/mdal_utils.cpp
vendored
Normal file
56
external/mdal/mdal_utils.cpp
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||||
|
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mdal_utils.hpp"
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
bool MDAL::fileExists( const std::string &filename )
|
||||||
|
{
|
||||||
|
std::ifstream in( filename );
|
||||||
|
return in.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MDAL::startsWith( const std::string &str, const std::string &substr )
|
||||||
|
{
|
||||||
|
return str.rfind( substr, 0 ) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> MDAL::split( const std::string &str, const std::string &delimiter, SplitBehaviour behaviour )
|
||||||
|
{
|
||||||
|
std::string remaining( str );
|
||||||
|
std::vector<std::string> list;
|
||||||
|
size_t pos = 0;
|
||||||
|
std::string token;
|
||||||
|
while ( ( pos = remaining.find( delimiter ) ) != std::string::npos )
|
||||||
|
{
|
||||||
|
token = remaining.substr( 0, pos );
|
||||||
|
|
||||||
|
if ( behaviour == SplitBehaviour::SkipEmptyParts )
|
||||||
|
{
|
||||||
|
if ( !token.empty() )
|
||||||
|
list.push_back( token );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
list.push_back( token );
|
||||||
|
|
||||||
|
remaining.erase( 0, pos + delimiter.length() );
|
||||||
|
}
|
||||||
|
list.push_back( remaining );
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t MDAL::toSizeT( const std::string &str )
|
||||||
|
{
|
||||||
|
int i = atoi( str.c_str() );
|
||||||
|
if ( i < 0 ) // consistent with atoi return
|
||||||
|
i = 0;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
double MDAL::toDouble( const std::string &str )
|
||||||
|
{
|
||||||
|
return atof( str.c_str() );
|
||||||
|
}
|
34
external/mdal/mdal_utils.hpp
vendored
Normal file
34
external/mdal/mdal_utils.hpp
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
MDAL - Mesh Data Abstraction Library (MIT License)
|
||||||
|
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MDAL_UTILS_HPP
|
||||||
|
#define MDAL_UTILS_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
namespace MDAL
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Return whether file exists */
|
||||||
|
bool fileExists( const std::string &filename );
|
||||||
|
|
||||||
|
// strings
|
||||||
|
bool startsWith( const std::string &str, const std::string &substr );
|
||||||
|
|
||||||
|
/** Return 0 if not possible to convert */
|
||||||
|
size_t toSizeT( const std::string &str );
|
||||||
|
double toDouble( const std::string &str );
|
||||||
|
|
||||||
|
enum SplitBehaviour
|
||||||
|
{
|
||||||
|
SkipEmptyParts,
|
||||||
|
KeepEmptyParts
|
||||||
|
};
|
||||||
|
std::vector<std::string> split( const std::string &str, const std::string &delimiter, SplitBehaviour behaviour );
|
||||||
|
|
||||||
|
} // namespace MDAL
|
||||||
|
#endif //MDAL_UTILS_HPP
|
78
images/themes/default/mIconMeshLayer.svg
Normal file
78
images/themes/default/mIconMeshLayer.svg
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
height="16"
|
||||||
|
width="16"
|
||||||
|
version="1.1"
|
||||||
|
id="svg10"
|
||||||
|
sodipodi:docname="mIconMeshLayer.svg"
|
||||||
|
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)">
|
||||||
|
<metadata
|
||||||
|
id="metadata16">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs14" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1680"
|
||||||
|
inkscape:window-height="1021"
|
||||||
|
id="namedview12"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="14.75"
|
||||||
|
inkscape:cx="8"
|
||||||
|
inkscape:cy="8"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="g8" />
|
||||||
|
<g
|
||||||
|
transform="translate(0.06779661,-15.457627)"
|
||||||
|
id="g8"
|
||||||
|
style="fill:#eeeeec;fill-rule:evenodd;stroke:#888a85;stroke-linecap:round;stroke-linejoin:round">
|
||||||
|
<rect
|
||||||
|
id="rect30"
|
||||||
|
width="5.9661016"
|
||||||
|
height="4.7457619"
|
||||||
|
x="1.6949153"
|
||||||
|
y="18.508474" />
|
||||||
|
<rect
|
||||||
|
id="rect32"
|
||||||
|
width="5.762712"
|
||||||
|
height="5.0847459"
|
||||||
|
x="1.7627119"
|
||||||
|
y="23.254236" />
|
||||||
|
<rect
|
||||||
|
id="rect34"
|
||||||
|
width="5.6949148"
|
||||||
|
height="4.7457619"
|
||||||
|
x="7.525424"
|
||||||
|
y="18.508474" />
|
||||||
|
<rect
|
||||||
|
id="rect36"
|
||||||
|
width="5.5593219"
|
||||||
|
height="5.0847468"
|
||||||
|
x="7.6610169"
|
||||||
|
y="23.254236" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.0 KiB |
@ -119,6 +119,7 @@ INCLUDE_DIRECTORIES(
|
|||||||
${CMAKE_SOURCE_DIR}/src/core/layout
|
${CMAKE_SOURCE_DIR}/src/core/layout
|
||||||
${CMAKE_SOURCE_DIR}/src/core/locator
|
${CMAKE_SOURCE_DIR}/src/core/locator
|
||||||
${CMAKE_SOURCE_DIR}/src/core/metadata
|
${CMAKE_SOURCE_DIR}/src/core/metadata
|
||||||
|
${CMAKE_SOURCE_DIR}/src/core/mesh
|
||||||
${CMAKE_SOURCE_DIR}/src/core/processing
|
${CMAKE_SOURCE_DIR}/src/core/processing
|
||||||
${CMAKE_SOURCE_DIR}/src/core/processing/models
|
${CMAKE_SOURCE_DIR}/src/core/processing/models
|
||||||
${CMAKE_SOURCE_DIR}/src/core/providers
|
${CMAKE_SOURCE_DIR}/src/core/providers
|
||||||
|
@ -378,6 +378,8 @@
|
|||||||
%Include raster/qgsrasterdataprovider.sip
|
%Include raster/qgsrasterdataprovider.sip
|
||||||
%Include raster/qgsrasterinterface.sip
|
%Include raster/qgsrasterinterface.sip
|
||||||
%Include raster/qgsrasterprojector.sip
|
%Include raster/qgsrasterprojector.sip
|
||||||
|
%Include mesh/qgsmeshdataprovider.sip
|
||||||
|
%Include mesh/qgsmeshlayer.sip
|
||||||
%Include geometry/qgsabstractgeometry.sip
|
%Include geometry/qgsabstractgeometry.sip
|
||||||
%Include geometry/qgsgeometry.sip
|
%Include geometry/qgsgeometry.sip
|
||||||
%Include geometry/qgspoint.sip
|
%Include geometry/qgspoint.sip
|
||||||
|
99
python/core/mesh/qgsmeshdataprovider.sip.in
Normal file
99
python/core/mesh/qgsmeshdataprovider.sip.in
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/mesh/qgsmeshdataprovider.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef QgsPoint QgsMeshVertex; //xyz coords of vertex
|
||||||
|
typedef QVector<int> QgsMeshFace; //list of vertex indexes
|
||||||
|
|
||||||
|
class QgsMeshSource /Abstract/
|
||||||
|
{
|
||||||
|
%Docstring
|
||||||
|
Mesh is a collection of vertices and faces in 2D or 3D space
|
||||||
|
- vertex - XY(Z) point (in the mesh's coordinate reference system)
|
||||||
|
- faces - sets of vertices forming a closed shape - typically triangles or quadrilaterals
|
||||||
|
|
||||||
|
Base on the underlying data provider/format, whole mesh is either stored in memory or
|
||||||
|
read on demand
|
||||||
|
|
||||||
|
.. versionadded:: 3.2
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgsmeshdataprovider.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
virtual ~QgsMeshSource();
|
||||||
|
|
||||||
|
virtual int vertexCount() const = 0;
|
||||||
|
%Docstring
|
||||||
|
Return number of vertices in the native mesh
|
||||||
|
|
||||||
|
:return: Number of vertices in the mesh
|
||||||
|
%End
|
||||||
|
|
||||||
|
virtual int faceCount() const = 0;
|
||||||
|
%Docstring
|
||||||
|
Return number of faces in the native mesh
|
||||||
|
|
||||||
|
:return: Number of faces in the mesh
|
||||||
|
%End
|
||||||
|
|
||||||
|
virtual QgsMeshVertex vertex( int index ) const = 0;
|
||||||
|
%Docstring
|
||||||
|
Factory for mesh vertex with index
|
||||||
|
|
||||||
|
:return: new mesh vertex on index
|
||||||
|
%End
|
||||||
|
|
||||||
|
virtual QgsMeshFace face( int index ) const = 0;
|
||||||
|
%Docstring
|
||||||
|
Factory for mesh face with index
|
||||||
|
|
||||||
|
:return: new mesh face on index
|
||||||
|
%End
|
||||||
|
};
|
||||||
|
|
||||||
|
class QgsMeshDataProvider: QgsDataProvider, QgsMeshSource
|
||||||
|
{
|
||||||
|
%Docstring
|
||||||
|
Base class for providing data for :py:class:`QgsMeshLayer`
|
||||||
|
|
||||||
|
Responsible for reading native mesh data
|
||||||
|
|
||||||
|
.. seealso:: :py:class:`QgsMeshSource`
|
||||||
|
|
||||||
|
.. versionadded:: 3.2
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgsmeshdataprovider.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
QgsMeshDataProvider( const QString &uri = QString() );
|
||||||
|
%Docstring
|
||||||
|
Ctor
|
||||||
|
%End
|
||||||
|
|
||||||
|
virtual QgsRectangle extent() const;
|
||||||
|
%Docstring
|
||||||
|
Returns the extent of the layer
|
||||||
|
|
||||||
|
:return: QgsRectangle containing the extent of the layer
|
||||||
|
%End
|
||||||
|
};
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/mesh/qgsmeshdataprovider.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
138
python/core/mesh/qgsmeshlayer.sip.in
Normal file
138
python/core/mesh/qgsmeshlayer.sip.in
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/mesh/qgsmeshlayer.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class QgsMeshLayer : QgsMapLayer
|
||||||
|
{
|
||||||
|
%Docstring
|
||||||
|
|
||||||
|
Represents a mesh layer supporting display of data on structured or unstructured meshes
|
||||||
|
|
||||||
|
The QgsMeshLayer is instantiated by specifying the name of a data provider,
|
||||||
|
such as mdal, and url defining the specific data set to connect to.
|
||||||
|
The vector layer constructor in turn instantiates a QgsMeshDataProvider subclass
|
||||||
|
corresponding to the provider type, and passes it the url. The data provider
|
||||||
|
connects to the data source.
|
||||||
|
|
||||||
|
The QgsMeshLayer provides a common interface to the different data types. It does not
|
||||||
|
yet support editing transactions.
|
||||||
|
|
||||||
|
The main data providers supported by QGIS are listed below.
|
||||||
|
|
||||||
|
\section mesh_providers Mesh data providers
|
||||||
|
|
||||||
|
\subsection mesh_memory Memory data providerType (mesh_memory)
|
||||||
|
|
||||||
|
The memory data provider is used to construct in memory data, for example scratch
|
||||||
|
data. There is no inherent persistent storage of the data. The data source uri is constructed.
|
||||||
|
Data can be populated by setMesh(const QString &vertices, const QString &faces), where
|
||||||
|
vertices and faces is comma separated coordinates and connections for mesh.
|
||||||
|
E.g. to create mesh with one quad and one triangle
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
QString uri(
|
||||||
|
"1.0, 2.0 \n" \
|
||||||
|
"2.0, 2.0 \n" \
|
||||||
|
"3.0, 2.0 \n" \
|
||||||
|
"2.0, 3.0 \n" \
|
||||||
|
"1.0, 3.0 \n" \
|
||||||
|
"---"
|
||||||
|
"0, 1, 3, 4 \n" \
|
||||||
|
"1, 2, 3 \n"
|
||||||
|
);
|
||||||
|
QgsMeshLayer *scratchLayer = new QgsMeshLayer(uri, "My Scratch layer", "memory_mesh");
|
||||||
|
|
||||||
|
\subsection mdal MDAL data provider (mdal)
|
||||||
|
|
||||||
|
Accesses data using the MDAL drivers (https://github.com/lutraconsulting/MDAL). The url
|
||||||
|
is the MDAL connection string. QGIS must be built with MDAL support to allow this provider.
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
QString uri = "test/land.2dm";
|
||||||
|
QgsMeshLayer *scratchLayer = new QgsMeshLayer(uri, "My Scratch Layer", "mdal");
|
||||||
|
|
||||||
|
.. versionadded:: 3.2
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgsmeshlayer.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit QgsMeshLayer( const QString &path = QString(), const QString &baseName = QString(), const QString &providerLib = "mesh_memory" );
|
||||||
|
%Docstring
|
||||||
|
Constructor - creates a mesh layer
|
||||||
|
|
||||||
|
The QgsMeshLayer is constructed by instantiating a data provider. The provider
|
||||||
|
interprets the supplied path (url) of the data source to connect to and access the
|
||||||
|
data.
|
||||||
|
|
||||||
|
:param path: The path or url of the parameter. Typically this encodes
|
||||||
|
parameters used by the data provider as url query items.
|
||||||
|
:param baseName: The name used to represent the layer in the legend
|
||||||
|
:param providerLib: The name of the data provider, e.g., "mesh_memory", "mdal"
|
||||||
|
%End
|
||||||
|
~QgsMeshLayer();
|
||||||
|
|
||||||
|
|
||||||
|
virtual QgsMeshDataProvider *dataProvider();
|
||||||
|
|
||||||
|
%Docstring
|
||||||
|
QgsMeshLayer cannot be copied.
|
||||||
|
%End
|
||||||
|
virtual QgsMeshLayer *clone() const /Factory/;
|
||||||
|
|
||||||
|
virtual QgsRectangle extent() const;
|
||||||
|
|
||||||
|
virtual QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) /Factory/;
|
||||||
|
virtual bool readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context );
|
||||||
|
|
||||||
|
virtual bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const;
|
||||||
|
|
||||||
|
|
||||||
|
QString providerType() const;
|
||||||
|
%Docstring
|
||||||
|
Return the provider type for this layer
|
||||||
|
%End
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QgsSymbol *nativeMeshSymbol();
|
||||||
|
%Docstring
|
||||||
|
Returns a line symbol used for rendering native mesh.
|
||||||
|
%End
|
||||||
|
|
||||||
|
QgsSymbol *triangularMeshSymbol();
|
||||||
|
%Docstring
|
||||||
|
Returns a line symbol used for rendering of triangular (derived) mesh.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`toggleTriangularMeshRendering`
|
||||||
|
%End
|
||||||
|
|
||||||
|
void toggleTriangularMeshRendering( bool toggle );
|
||||||
|
%Docstring
|
||||||
|
Toggle rendering of triangular (derived) mesh. Off by default
|
||||||
|
%End
|
||||||
|
|
||||||
|
private: // Private methods
|
||||||
|
QgsMeshLayer( const QgsMeshLayer &rhs );
|
||||||
|
};
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/mesh/qgsmeshlayer.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
28
python/core/mesh/qgsnativemesh.sip.in
Normal file
28
python/core/mesh/qgsnativemesh.sip.in
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/mesh/qgsnativemesh.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef QgsPoint QgsMeshVertex; //xyz coords of vertex
|
||||||
|
typedef std::vector<int> QgsMeshFace; //list of vertex indexes
|
||||||
|
|
||||||
|
struct QgsNativeMesh
|
||||||
|
{
|
||||||
|
std::vector<QgsMeshVertex> vertices;
|
||||||
|
std::vector<QgsMeshFace> faces;
|
||||||
|
};
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/mesh/qgsnativemesh.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
@ -394,7 +394,8 @@ Item that represents a layer that can be opened with one of the providers
|
|||||||
TableLayer,
|
TableLayer,
|
||||||
Database,
|
Database,
|
||||||
Table,
|
Table,
|
||||||
Plugin
|
Plugin,
|
||||||
|
Mesh
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -470,6 +471,10 @@ Returns the icon name of the given ``layerType``
|
|||||||
static QIcon iconTable();
|
static QIcon iconTable();
|
||||||
static QIcon iconRaster();
|
static QIcon iconRaster();
|
||||||
static QIcon iconDefault();
|
static QIcon iconDefault();
|
||||||
|
static QIcon iconMesh();
|
||||||
|
%Docstring
|
||||||
|
Return icon for mesh layer type
|
||||||
|
%End
|
||||||
|
|
||||||
virtual QString layerName() const;
|
virtual QString layerName() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
|
@ -38,6 +38,10 @@ to generic QgsVectorDataProvider's) depends on it.
|
|||||||
{
|
{
|
||||||
sipType = sipType_QgsRasterDataProvider;
|
sipType = sipType_QgsRasterDataProvider;
|
||||||
}
|
}
|
||||||
|
else if ( qobject_cast<QgsMeshDataProvider *>( sipCpp ) )
|
||||||
|
{
|
||||||
|
sipType = sipType_QgsMeshDataProvider;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sipType = 0;
|
sipType = 0;
|
||||||
|
@ -41,6 +41,9 @@ This is the base class for all map layer types (vector, raster).
|
|||||||
case QgsMapLayer::PluginLayer:
|
case QgsMapLayer::PluginLayer:
|
||||||
sipType = sipType_QgsPluginLayer;
|
sipType = sipType_QgsPluginLayer;
|
||||||
break;
|
break;
|
||||||
|
case QgsMapLayer::MeshLayer:
|
||||||
|
sipType = sipType_QgsMeshLayer;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
sipType = nullptr;
|
sipType = nullptr;
|
||||||
break;
|
break;
|
||||||
@ -53,7 +56,8 @@ This is the base class for all map layer types (vector, raster).
|
|||||||
{
|
{
|
||||||
VectorLayer,
|
VectorLayer,
|
||||||
RasterLayer,
|
RasterLayer,
|
||||||
PluginLayer
|
PluginLayer,
|
||||||
|
MeshLayer
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PropertyType
|
enum PropertyType
|
||||||
|
@ -52,6 +52,14 @@ Get vector layer from uri if possible, otherwise returns 0 and error is set
|
|||||||
%Docstring
|
%Docstring
|
||||||
Get raster layer from uri if possible, otherwise returns 0 and error is set
|
Get raster layer from uri if possible, otherwise returns 0 and error is set
|
||||||
|
|
||||||
|
:param owner: set to true if caller becomes owner
|
||||||
|
:param error: set to error message if cannot get raster
|
||||||
|
%End
|
||||||
|
|
||||||
|
QgsMeshLayer *meshLayer( bool &owner, QString &error ) const;
|
||||||
|
%Docstring
|
||||||
|
Get mesh layer from uri if possible, otherwise returns 0 and error is set
|
||||||
|
|
||||||
:param owner: set to true if caller becomes owner
|
:param owner: set to true if caller becomes owner
|
||||||
:param error: set to error message if cannot get raster
|
:param error: set to error message if cannot get raster
|
||||||
%End
|
%End
|
||||||
|
@ -162,6 +162,7 @@ buildSupportedRasterFileFilter to a string, which is then returned.
|
|||||||
|
|
||||||
This replaces :py:func:`QgsRasterLayer.buildSupportedRasterFileFilter()`
|
This replaces :py:func:`QgsRasterLayer.buildSupportedRasterFileFilter()`
|
||||||
%End
|
%End
|
||||||
|
|
||||||
virtual QString databaseDrivers() const;
|
virtual QString databaseDrivers() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
Return a string containing the available database drivers
|
Return a string containing the available database drivers
|
||||||
|
@ -142,6 +142,12 @@ QVariantMap QgsPackageAlgorithm::processAlgorithm( const QVariantMap ¶meters
|
|||||||
feedback->pushDebugInfo( QObject::tr( "Packaging plugin layers is not supported." ) );
|
feedback->pushDebugInfo( QObject::tr( "Packaging plugin layers is not supported." ) );
|
||||||
errored = true;
|
errored = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case QgsMapLayer::MeshLayer:
|
||||||
|
//not supported
|
||||||
|
feedback->pushDebugInfo( QObject::tr( "Packaging mesh layers is not supported." ) );
|
||||||
|
errored = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,6 +599,7 @@ INCLUDE_DIRECTORIES(
|
|||||||
${CMAKE_SOURCE_DIR}/src/core/geometry
|
${CMAKE_SOURCE_DIR}/src/core/geometry
|
||||||
${CMAKE_SOURCE_DIR}/src/core/geocms/geonode
|
${CMAKE_SOURCE_DIR}/src/core/geocms/geonode
|
||||||
${CMAKE_SOURCE_DIR}/src/core/metadata
|
${CMAKE_SOURCE_DIR}/src/core/metadata
|
||||||
|
${CMAKE_SOURCE_DIR}/src/core/mesh
|
||||||
${CMAKE_SOURCE_DIR}/src/core/layertree
|
${CMAKE_SOURCE_DIR}/src/core/layertree
|
||||||
${CMAKE_SOURCE_DIR}/src/core/locator
|
${CMAKE_SOURCE_DIR}/src/core/locator
|
||||||
${CMAKE_SOURCE_DIR}/src/core/providers/memory
|
${CMAKE_SOURCE_DIR}/src/core/providers/memory
|
||||||
|
@ -228,6 +228,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
|
|||||||
#include "qgsmessageviewer.h"
|
#include "qgsmessageviewer.h"
|
||||||
#include "qgsmessagebar.h"
|
#include "qgsmessagebar.h"
|
||||||
#include "qgsmessagebaritem.h"
|
#include "qgsmessagebaritem.h"
|
||||||
|
#include "qgsmeshlayer.h"
|
||||||
#include "qgsmemoryproviderutils.h"
|
#include "qgsmemoryproviderutils.h"
|
||||||
#include "qgsmimedatautils.h"
|
#include "qgsmimedatautils.h"
|
||||||
#include "qgsmessagelog.h"
|
#include "qgsmessagelog.h"
|
||||||
@ -1667,6 +1668,11 @@ void QgisApp::handleDropUriList( const QgsMimeDataUtils::UriList &lst )
|
|||||||
{
|
{
|
||||||
addRasterLayer( uri, u.name, u.providerKey );
|
addRasterLayer( uri, u.name, u.providerKey );
|
||||||
}
|
}
|
||||||
|
else if ( u.layerType == QLatin1String( "mesh" ) )
|
||||||
|
{
|
||||||
|
QgsMeshLayer *layer = new QgsMeshLayer( uri, u.name, u.providerKey );
|
||||||
|
addMapLayer( layer );
|
||||||
|
}
|
||||||
else if ( u.layerType == QLatin1String( "plugin" ) )
|
else if ( u.layerType == QLatin1String( "plugin" ) )
|
||||||
{
|
{
|
||||||
addPluginLayer( uri, u.name, u.providerKey );
|
addPluginLayer( uri, u.name, u.providerKey );
|
||||||
|
@ -447,6 +447,12 @@ SET(QGIS_CORE_SRCS
|
|||||||
raster/qgssinglebandpseudocolorrenderer.cpp
|
raster/qgssinglebandpseudocolorrenderer.cpp
|
||||||
raster/qgshillshaderenderer.cpp
|
raster/qgshillshaderenderer.cpp
|
||||||
|
|
||||||
|
mesh/qgsmeshdataprovider.cpp
|
||||||
|
mesh/qgsmeshlayer.cpp
|
||||||
|
mesh/qgsmeshlayerrenderer.cpp
|
||||||
|
mesh/qgsmeshmemorydataprovider.cpp
|
||||||
|
mesh/qgstriangularmesh.cpp
|
||||||
|
|
||||||
geometry/qgsabstractgeometry.cpp
|
geometry/qgsabstractgeometry.cpp
|
||||||
geometry/qgsbox3d.cpp
|
geometry/qgsbox3d.cpp
|
||||||
geometry/qgscircle.cpp
|
geometry/qgscircle.cpp
|
||||||
@ -684,6 +690,10 @@ SET(QGIS_CORE_MOC_HDRS
|
|||||||
raster/qgsrasterlayerrenderer.h
|
raster/qgsrasterlayerrenderer.h
|
||||||
raster/qgsrasterprojector.h
|
raster/qgsrasterprojector.h
|
||||||
|
|
||||||
|
mesh/qgsmeshdataprovider.h
|
||||||
|
mesh/qgsmeshlayer.h
|
||||||
|
mesh/qgsmeshmemorydataprovider.h
|
||||||
|
|
||||||
geometry/qgsabstractgeometry.h
|
geometry/qgsabstractgeometry.h
|
||||||
geometry/qgsgeometry.h
|
geometry/qgsgeometry.h
|
||||||
geometry/qgspoint.h
|
geometry/qgspoint.h
|
||||||
@ -1061,6 +1071,9 @@ SET(QGIS_CORE_HDRS
|
|||||||
raster/qgssinglebandpseudocolorrenderer.h
|
raster/qgssinglebandpseudocolorrenderer.h
|
||||||
raster/qgshillshaderenderer.h
|
raster/qgshillshaderenderer.h
|
||||||
|
|
||||||
|
mesh/qgstriangularmesh.h
|
||||||
|
mesh/qgsmeshlayerrenderer.h
|
||||||
|
|
||||||
scalebar/qgsdoubleboxscalebarrenderer.h
|
scalebar/qgsdoubleboxscalebarrenderer.h
|
||||||
scalebar/qgsnumericscalebarrenderer.h
|
scalebar/qgsnumericscalebarrenderer.h
|
||||||
scalebar/qgsscalebarsettings.h
|
scalebar/qgsscalebarsettings.h
|
||||||
@ -1181,6 +1194,7 @@ INCLUDE_DIRECTORIES(
|
|||||||
scalebar
|
scalebar
|
||||||
symbology
|
symbology
|
||||||
metadata
|
metadata
|
||||||
|
mesh
|
||||||
${CMAKE_SOURCE_DIR}/external/nmea
|
${CMAKE_SOURCE_DIR}/external/nmea
|
||||||
)
|
)
|
||||||
IF (WITH_INTERNAL_QEXTSERIALPORT)
|
IF (WITH_INTERNAL_QEXTSERIALPORT)
|
||||||
|
@ -3642,6 +3642,8 @@ static QVariant fcnGetLayerProperty( const QVariantList &values, const QgsExpres
|
|||||||
return QCoreApplication::translate( "expressions", "Vector" );
|
return QCoreApplication::translate( "expressions", "Vector" );
|
||||||
case QgsMapLayer::RasterLayer:
|
case QgsMapLayer::RasterLayer:
|
||||||
return QCoreApplication::translate( "expressions", "Raster" );
|
return QCoreApplication::translate( "expressions", "Raster" );
|
||||||
|
case QgsMapLayer::MeshLayer:
|
||||||
|
return QCoreApplication::translate( "expressions", "Mesh" );
|
||||||
case QgsMapLayer::PluginLayer:
|
case QgsMapLayer::PluginLayer:
|
||||||
return QCoreApplication::translate( "expressions", "Plugin" );
|
return QCoreApplication::translate( "expressions", "Plugin" );
|
||||||
}
|
}
|
||||||
|
40
src/core/mesh/qgsmeshdataprovider.cpp
Normal file
40
src/core/mesh/qgsmeshdataprovider.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmeshdataprovider.cpp
|
||||||
|
-----------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "qgsmeshdataprovider.h"
|
||||||
|
|
||||||
|
QgsMeshDataProvider::QgsMeshDataProvider( const QString &uri )
|
||||||
|
: QgsDataProvider( uri )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QgsRectangle QgsMeshDataProvider::extent() const
|
||||||
|
{
|
||||||
|
QgsRectangle rec;
|
||||||
|
rec.setMinimal();
|
||||||
|
for ( int i = 0; i < vertexCount(); ++i )
|
||||||
|
{
|
||||||
|
QgsMeshVertex v = vertex( i );
|
||||||
|
rec.setXMinimum( std::min( rec.xMinimum(), v.x() ) );
|
||||||
|
rec.setYMinimum( std::min( rec.yMinimum(), v.y() ) );
|
||||||
|
rec.setXMaximum( std::max( rec.xMaximum(), v.x() ) );
|
||||||
|
rec.setYMaximum( std::max( rec.yMaximum(), v.y() ) );
|
||||||
|
}
|
||||||
|
return rec;
|
||||||
|
|
||||||
|
}
|
98
src/core/mesh/qgsmeshdataprovider.h
Normal file
98
src/core/mesh/qgsmeshdataprovider.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmeshdataprovider.h
|
||||||
|
---------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QGSMESHDATAPROVIDER_H
|
||||||
|
#define QGSMESHDATAPROVIDER_H
|
||||||
|
|
||||||
|
#include "qgis_core.h"
|
||||||
|
#include "qgspoint.h"
|
||||||
|
#include "qgsrectangle.h"
|
||||||
|
#include "qgsdataprovider.h"
|
||||||
|
|
||||||
|
#include <QVector>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
typedef QgsPoint QgsMeshVertex; //xyz coords of vertex
|
||||||
|
typedef QVector<int> QgsMeshFace; //list of vertex indexes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
* Mesh is a collection of vertices and faces in 2D or 3D space
|
||||||
|
* - vertex - XY(Z) point (in the mesh's coordinate reference system)
|
||||||
|
* - faces - sets of vertices forming a closed shape - typically triangles or quadrilaterals
|
||||||
|
*
|
||||||
|
* Base on the underlying data provider/format, whole mesh is either stored in memory or
|
||||||
|
* read on demand
|
||||||
|
*
|
||||||
|
* \since QGIS 3.2
|
||||||
|
*/
|
||||||
|
class CORE_EXPORT QgsMeshSource SIP_ABSTRACT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Dtor
|
||||||
|
virtual ~QgsMeshSource() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Return number of vertices in the native mesh
|
||||||
|
* \returns Number of vertices in the mesh
|
||||||
|
*/
|
||||||
|
virtual int vertexCount() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Return number of faces in the native mesh
|
||||||
|
* \returns Number of faces in the mesh
|
||||||
|
*/
|
||||||
|
virtual int faceCount() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Factory for mesh vertex with index
|
||||||
|
* \returns new mesh vertex on index
|
||||||
|
*/
|
||||||
|
virtual QgsMeshVertex vertex( int index ) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Factory for mesh face with index
|
||||||
|
* \returns new mesh face on index
|
||||||
|
*/
|
||||||
|
virtual QgsMeshFace face( int index ) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
* Base class for providing data for QgsMeshLayer
|
||||||
|
*
|
||||||
|
* Responsible for reading native mesh data
|
||||||
|
*
|
||||||
|
* \see QgsMeshSource
|
||||||
|
* \since QGIS 3.2
|
||||||
|
*/
|
||||||
|
class CORE_EXPORT QgsMeshDataProvider: public QgsDataProvider, public QgsMeshSource
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! Ctor
|
||||||
|
QgsMeshDataProvider( const QString &uri = QString() );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the extent of the layer
|
||||||
|
* \returns QgsRectangle containing the extent of the layer
|
||||||
|
*/
|
||||||
|
virtual QgsRectangle extent() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QGSMESHDATAPROVIDER_H
|
214
src/core/mesh/qgsmeshlayer.cpp
Normal file
214
src/core/mesh/qgsmeshlayer.cpp
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmeshlayer.cpp
|
||||||
|
----------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
|
#include "qgsfillsymbollayer.h"
|
||||||
|
#include "qgslogger.h"
|
||||||
|
#include "qgsmeshdataprovider.h"
|
||||||
|
#include "qgsmeshlayer.h"
|
||||||
|
#include "qgsmeshlayerrenderer.h"
|
||||||
|
#include "qgsproviderregistry.h"
|
||||||
|
#include "qgstriangularmesh.h"
|
||||||
|
|
||||||
|
QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
|
||||||
|
const QString &baseName,
|
||||||
|
const QString &providerKey )
|
||||||
|
: QgsMapLayer( MeshLayer, baseName, meshLayerPath )
|
||||||
|
, mProviderKey( providerKey )
|
||||||
|
{
|
||||||
|
// load data
|
||||||
|
setDataProvider( providerKey );
|
||||||
|
|
||||||
|
QgsSymbolLayerList l1;
|
||||||
|
l1 << new QgsSimpleFillSymbolLayer( Qt::white, Qt::NoBrush, Qt::black, Qt::SolidLine, 1.0 );
|
||||||
|
mNativeMeshSymbol.reset( new QgsFillSymbol( l1 ) );
|
||||||
|
|
||||||
|
|
||||||
|
toggleTriangularMeshRendering( false );
|
||||||
|
|
||||||
|
} // QgsMeshLayer ctor
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QgsMeshLayer::~QgsMeshLayer()
|
||||||
|
{
|
||||||
|
if ( mDataProvider )
|
||||||
|
delete mDataProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshDataProvider *QgsMeshLayer::dataProvider()
|
||||||
|
{
|
||||||
|
return mDataProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QgsMeshDataProvider *QgsMeshLayer::dataProvider() const
|
||||||
|
{
|
||||||
|
return mDataProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshLayer *QgsMeshLayer::clone() const
|
||||||
|
{
|
||||||
|
QgsMeshLayer *layer = new QgsMeshLayer( source(), name(), mProviderKey );
|
||||||
|
QgsMapLayer::clone( layer );
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsRectangle QgsMeshLayer::extent() const
|
||||||
|
{
|
||||||
|
if ( mDataProvider )
|
||||||
|
return mDataProvider->extent();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QgsRectangle rec;
|
||||||
|
rec.setMinimal();
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMeshLayer::providerType() const
|
||||||
|
{
|
||||||
|
return mProviderKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMesh *QgsMeshLayer::nativeMesh() SIP_SKIP
|
||||||
|
{
|
||||||
|
return mNativeMesh.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QgsTriangularMesh *QgsMeshLayer::triangularMesh() SIP_SKIP
|
||||||
|
{
|
||||||
|
return mTriangularMesh.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsSymbol *QgsMeshLayer::nativeMeshSymbol()
|
||||||
|
{
|
||||||
|
return mNativeMeshSymbol.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsSymbol *QgsMeshLayer::triangularMeshSymbol()
|
||||||
|
{
|
||||||
|
return mTriangularMeshSymbol.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshLayer::toggleTriangularMeshRendering( bool toggle )
|
||||||
|
{
|
||||||
|
if ( toggle && mTriangularMeshSymbol )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( toggle )
|
||||||
|
{
|
||||||
|
QgsSymbolLayerList l2;
|
||||||
|
l2 << new QgsSimpleFillSymbolLayer( Qt::white, Qt::NoBrush, Qt::red, Qt::SolidLine, 0.26 );
|
||||||
|
mTriangularMeshSymbol.reset( new QgsFillSymbol( l2 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mTriangularMeshSymbol.reset();
|
||||||
|
}
|
||||||
|
triggerRepaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshLayer::fillNativeMesh()
|
||||||
|
{
|
||||||
|
Q_ASSERT( !mNativeMesh );
|
||||||
|
|
||||||
|
mNativeMesh.reset( new QgsMesh() );
|
||||||
|
|
||||||
|
if ( !( dataProvider() && dataProvider()->isValid() ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
mNativeMesh->vertices.resize( dataProvider()->vertexCount() );
|
||||||
|
for ( int i = 0; i < dataProvider()->vertexCount(); ++i )
|
||||||
|
{
|
||||||
|
mNativeMesh->vertices[i] = dataProvider()->vertex( i );
|
||||||
|
}
|
||||||
|
|
||||||
|
mNativeMesh->faces.resize( dataProvider()->faceCount() );
|
||||||
|
for ( int i = 0; i < dataProvider()->faceCount(); ++i )
|
||||||
|
{
|
||||||
|
mNativeMesh->faces[i] = dataProvider()->face( i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMapLayerRenderer *QgsMeshLayer::createMapRenderer( QgsRenderContext &rendererContext )
|
||||||
|
{
|
||||||
|
if ( !mNativeMesh )
|
||||||
|
{
|
||||||
|
// lazy loading of mesh data
|
||||||
|
fillNativeMesh();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !mTriangularMesh )
|
||||||
|
mTriangularMesh.reset( new QgsTriangularMesh() );
|
||||||
|
|
||||||
|
mTriangularMesh->update( mNativeMesh.get(), &rendererContext );
|
||||||
|
return new QgsMeshLayerRenderer( this, rendererContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsMeshLayer::readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context )
|
||||||
|
{
|
||||||
|
Q_UNUSED( node );
|
||||||
|
Q_UNUSED( errorMessage );
|
||||||
|
Q_UNUSED( context );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsMeshLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const
|
||||||
|
{
|
||||||
|
Q_UNUSED( node );
|
||||||
|
Q_UNUSED( doc );
|
||||||
|
Q_UNUSED( errorMessage );
|
||||||
|
Q_UNUSED( context );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsMeshLayer::setDataProvider( QString const &provider )
|
||||||
|
{
|
||||||
|
Q_ASSERT( !mDataProvider ); //called from ctor
|
||||||
|
|
||||||
|
mProviderKey = provider;
|
||||||
|
QString dataSource = mDataSource;
|
||||||
|
|
||||||
|
mDataProvider = qobject_cast<QgsMeshDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, dataSource ) );
|
||||||
|
if ( !mDataProvider )
|
||||||
|
{
|
||||||
|
QgsDebugMsgLevel( QStringLiteral( "Unable to get mesh data provider" ), 2 );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDataProvider->setParent( this );
|
||||||
|
QgsDebugMsgLevel( QStringLiteral( "Instantiated the mesh data provider plugin" ), 2 );
|
||||||
|
|
||||||
|
mValid = mDataProvider->isValid();
|
||||||
|
if ( !mValid )
|
||||||
|
{
|
||||||
|
QgsDebugMsgLevel( QStringLiteral( "Invalid mesh provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( provider == QStringLiteral( "mesh_memory" ) )
|
||||||
|
{
|
||||||
|
// required so that source differs between memory layers
|
||||||
|
mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} // QgsMeshLayer:: setDataProvider
|
179
src/core/mesh/qgsmeshlayer.h
Normal file
179
src/core/mesh/qgsmeshlayer.h
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmeshlayer.h
|
||||||
|
--------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QGSMESHLAYER_H
|
||||||
|
#define QGSMESHLAYER_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "qgis_core.h"
|
||||||
|
#include "qgsmaplayer.h"
|
||||||
|
#include "qgsrendercontext.h"
|
||||||
|
#include "qgsmeshdataprovider.h"
|
||||||
|
|
||||||
|
class QgsMapLayerRenderer;
|
||||||
|
class QgsSymbol;
|
||||||
|
class QgsTriangularMesh;
|
||||||
|
struct QgsMesh;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
*
|
||||||
|
* Represents a mesh layer supporting display of data on structured or unstructured meshes
|
||||||
|
*
|
||||||
|
* The QgsMeshLayer is instantiated by specifying the name of a data provider,
|
||||||
|
* such as mdal, and url defining the specific data set to connect to.
|
||||||
|
* The vector layer constructor in turn instantiates a QgsMeshDataProvider subclass
|
||||||
|
* corresponding to the provider type, and passes it the url. The data provider
|
||||||
|
* connects to the data source.
|
||||||
|
*
|
||||||
|
* The QgsMeshLayer provides a common interface to the different data types. It does not
|
||||||
|
* yet support editing transactions.
|
||||||
|
*
|
||||||
|
* The main data providers supported by QGIS are listed below.
|
||||||
|
*
|
||||||
|
* \section mesh_providers Mesh data providers
|
||||||
|
*
|
||||||
|
* \subsection mesh_memory Memory data providerType (mesh_memory)
|
||||||
|
*
|
||||||
|
* The memory data provider is used to construct in memory data, for example scratch
|
||||||
|
* data. There is no inherent persistent storage of the data. The data source uri is constructed.
|
||||||
|
* Data can be populated by setMesh(const QString &vertices, const QString &faces), where
|
||||||
|
* vertices and faces is comma separated coordinates and connections for mesh.
|
||||||
|
* E.g. to create mesh with one quad and one triangle
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* QString uri(
|
||||||
|
* "1.0, 2.0 \n" \
|
||||||
|
* "2.0, 2.0 \n" \
|
||||||
|
* "3.0, 2.0 \n" \
|
||||||
|
* "2.0, 3.0 \n" \
|
||||||
|
* "1.0, 3.0 \n" \
|
||||||
|
* "---"
|
||||||
|
* "0, 1, 3, 4 \n" \
|
||||||
|
* "1, 2, 3 \n"
|
||||||
|
* );
|
||||||
|
* QgsMeshLayer *scratchLayer = new QgsMeshLayer(uri, "My Scratch layer", "memory_mesh");
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* \subsection mdal MDAL data provider (mdal)
|
||||||
|
*
|
||||||
|
* Accesses data using the MDAL drivers (https://github.com/lutraconsulting/MDAL). The url
|
||||||
|
* is the MDAL connection string. QGIS must be built with MDAL support to allow this provider.
|
||||||
|
|
||||||
|
* \code
|
||||||
|
* QString uri = "test/land.2dm";
|
||||||
|
* QgsMeshLayer *scratchLayer = new QgsMeshLayer(uri, "My Scratch Layer", "mdal");
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* \since QGIS 3.2
|
||||||
|
*/
|
||||||
|
class CORE_EXPORT QgsMeshLayer : public QgsMapLayer
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor - creates a mesh layer
|
||||||
|
*
|
||||||
|
* The QgsMeshLayer is constructed by instantiating a data provider. The provider
|
||||||
|
* interprets the supplied path (url) of the data source to connect to and access the
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* \param path The path or url of the parameter. Typically this encodes
|
||||||
|
* parameters used by the data provider as url query items.
|
||||||
|
* \param baseName The name used to represent the layer in the legend
|
||||||
|
* \param providerLib The name of the data provider, e.g., "mesh_memory", "mdal"
|
||||||
|
*/
|
||||||
|
explicit QgsMeshLayer( const QString &path = QString(), const QString &baseName = QString(), const QString &providerLib = "mesh_memory" );
|
||||||
|
~QgsMeshLayer() override;
|
||||||
|
|
||||||
|
//! QgsMeshLayer cannot be copied.
|
||||||
|
QgsMeshLayer( const QgsMeshLayer &rhs ) = delete;
|
||||||
|
//! QgsMeshLayer cannot be copied.
|
||||||
|
QgsMeshLayer &operator=( QgsMeshLayer const &rhs ) = delete;
|
||||||
|
|
||||||
|
QgsMeshDataProvider *dataProvider() override;
|
||||||
|
const QgsMeshDataProvider *dataProvider() const override SIP_SKIP;
|
||||||
|
QgsMeshLayer *clone() const override SIP_FACTORY;
|
||||||
|
QgsRectangle extent() const override;
|
||||||
|
virtual QgsMapLayerRenderer *createMapRenderer( QgsRenderContext &rendererContext ) override SIP_FACTORY;
|
||||||
|
bool readSymbology( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context ) override;
|
||||||
|
bool writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context ) const override;
|
||||||
|
|
||||||
|
//! Return the provider type for this layer
|
||||||
|
QString providerType() const;
|
||||||
|
|
||||||
|
//! return native mesh (nullprt before rendering)
|
||||||
|
QgsMesh *nativeMesh() SIP_SKIP;
|
||||||
|
|
||||||
|
//! return triangular mesh (nullprt before rendering)
|
||||||
|
QgsTriangularMesh *triangularMesh() SIP_SKIP;
|
||||||
|
|
||||||
|
//! Returns a line symbol used for rendering native mesh.
|
||||||
|
QgsSymbol *nativeMeshSymbol();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a line symbol used for rendering of triangular (derived) mesh.
|
||||||
|
* \see toggleTriangularMeshRendering
|
||||||
|
*/
|
||||||
|
QgsSymbol *triangularMeshSymbol();
|
||||||
|
|
||||||
|
//! Toggle rendering of triangular (derived) mesh. Off by default
|
||||||
|
void toggleTriangularMeshRendering( bool toggle );
|
||||||
|
|
||||||
|
private: // Private methods
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the provider is in read-only mode
|
||||||
|
*/
|
||||||
|
bool isReadOnly() const override {return true;}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind layer to a specific data provider
|
||||||
|
* \param provider provider key string, must match a valid QgsMeshDataProvider key. E.g. "mesh_memory", etc.
|
||||||
|
*/
|
||||||
|
bool setDataProvider( QString const &provider );
|
||||||
|
|
||||||
|
#ifdef SIP_RUN
|
||||||
|
QgsMeshLayer( const QgsMeshLayer &rhs );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
void fillNativeMesh();
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Pointer to data provider derived from the abastract base class QgsMeshDataProvider
|
||||||
|
QgsMeshDataProvider *mDataProvider = nullptr;
|
||||||
|
|
||||||
|
//! Data provider key
|
||||||
|
QString mProviderKey;
|
||||||
|
|
||||||
|
//! Pointer to native mesh structure, used as cache for rendering
|
||||||
|
std::unique_ptr<QgsMesh> mNativeMesh;
|
||||||
|
|
||||||
|
//! Pointer to derived mesh structure
|
||||||
|
std::unique_ptr<QgsTriangularMesh> mTriangularMesh;
|
||||||
|
|
||||||
|
//! rendering native mesh
|
||||||
|
std::unique_ptr<QgsSymbol> mNativeMeshSymbol;
|
||||||
|
|
||||||
|
//! rendering triangular mesh
|
||||||
|
std::unique_ptr<QgsSymbol> mTriangularMeshSymbol;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //QGSMESHLAYER_H
|
93
src/core/mesh/qgsmeshlayerrenderer.cpp
Normal file
93
src/core/mesh/qgsmeshlayerrenderer.cpp
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmeshlayerrenderer.cpp
|
||||||
|
------------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "qgsmeshlayerrenderer.h"
|
||||||
|
|
||||||
|
#include "qgsfield.h"
|
||||||
|
#include "qgslogger.h"
|
||||||
|
#include "qgsmeshlayer.h"
|
||||||
|
#include "qgspointxy.h"
|
||||||
|
#include "qgsrenderer.h"
|
||||||
|
#include "qgssinglesymbolrenderer.h"
|
||||||
|
#include "qgssymbol.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QgsMeshLayerRenderer::QgsMeshLayerRenderer( QgsMeshLayer *layer, QgsRenderContext &context )
|
||||||
|
: QgsMapLayerRenderer( layer->id() )
|
||||||
|
, mContext( context )
|
||||||
|
{
|
||||||
|
// make copies for mesh data
|
||||||
|
Q_ASSERT( layer->nativeMesh() );
|
||||||
|
Q_ASSERT( layer->triangularMesh() );
|
||||||
|
mNativeMesh = *( layer->nativeMesh() );
|
||||||
|
mTriangularMesh = *( layer->triangularMesh() );
|
||||||
|
|
||||||
|
// make copies for symbols
|
||||||
|
if ( layer->nativeMeshSymbol() )
|
||||||
|
{
|
||||||
|
mNativeMeshSymbol.reset( layer->nativeMeshSymbol()->clone() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( layer->triangularMeshSymbol() )
|
||||||
|
{
|
||||||
|
mTriangularMeshSymbol.reset( layer->triangularMeshSymbol()->clone() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsMeshLayerRenderer::render()
|
||||||
|
{
|
||||||
|
renderMesh( mNativeMeshSymbol, mNativeMesh.faces ); // native mesh
|
||||||
|
renderMesh( mTriangularMeshSymbol, mTriangularMesh.triangles() ); // triangular mesh
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMeshLayerRenderer::renderMesh( const std::unique_ptr<QgsSymbol> &symbol, const QVector<QgsMeshFace> &faces )
|
||||||
|
{
|
||||||
|
if ( !symbol )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QgsFields fields;
|
||||||
|
QgsSingleSymbolRenderer renderer( symbol->clone() );
|
||||||
|
renderer.startRender( mContext, fields );
|
||||||
|
|
||||||
|
for ( int i = 0; i < faces.size(); ++i )
|
||||||
|
{
|
||||||
|
if ( mContext.renderingStopped() )
|
||||||
|
break;
|
||||||
|
|
||||||
|
const QgsMeshFace &face = faces[i];
|
||||||
|
QgsFeature feat;
|
||||||
|
feat.setFields( fields );
|
||||||
|
QVector<QgsPointXY> ring;
|
||||||
|
for ( int j = 0; j < face.size(); ++j )
|
||||||
|
{
|
||||||
|
int vertex_id = face[j];
|
||||||
|
Q_ASSERT( vertex_id < mTriangularMesh.vertices().size() ); //Triangular mesh vertices contains also native mesh vertices
|
||||||
|
const QgsPoint &vertex = mTriangularMesh.vertices()[vertex_id];
|
||||||
|
ring.append( vertex );
|
||||||
|
}
|
||||||
|
QgsPolygonXY polygon;
|
||||||
|
polygon.append( ring );
|
||||||
|
QgsGeometry geom = QgsGeometry::fromPolygonXY( polygon );
|
||||||
|
feat.setGeometry( geom );
|
||||||
|
renderer.renderFeature( feat, mContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.stopRender( mContext );
|
||||||
|
}
|
72
src/core/mesh/qgsmeshlayerrenderer.h
Normal file
72
src/core/mesh/qgsmeshlayerrenderer.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmeshlayerrenderer.h
|
||||||
|
----------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QGSMESHLAYERRENDERER_H
|
||||||
|
#define QGSMESHLAYERRENDERER_H
|
||||||
|
|
||||||
|
class QgsMeshLayer;
|
||||||
|
class QgsSymbol;
|
||||||
|
|
||||||
|
#define SIP_NO_FILE
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "qgis.h"
|
||||||
|
|
||||||
|
#include "qgsmaplayerrenderer.h"
|
||||||
|
#include "qgsrendercontext.h"
|
||||||
|
#include "qgstriangularmesh.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
* Implementation of threaded rendering for mesh layers.
|
||||||
|
*
|
||||||
|
* \since QGIS 3.2
|
||||||
|
* \note not available in Python bindings
|
||||||
|
*/
|
||||||
|
class QgsMeshLayerRenderer : public QgsMapLayerRenderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Ctor
|
||||||
|
QgsMeshLayerRenderer( QgsMeshLayer *layer, QgsRenderContext &context );
|
||||||
|
|
||||||
|
~QgsMeshLayerRenderer() override = default;
|
||||||
|
bool render() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void renderMesh( const std::unique_ptr<QgsSymbol> &symbol, const QVector<QgsMeshFace> &faces );
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// copy from mesh layer
|
||||||
|
QgsMesh mNativeMesh;
|
||||||
|
|
||||||
|
// copy from mesh layer
|
||||||
|
QgsTriangularMesh mTriangularMesh;
|
||||||
|
|
||||||
|
// copy from mesh layer
|
||||||
|
std::unique_ptr<QgsSymbol> mNativeMeshSymbol = nullptr;
|
||||||
|
|
||||||
|
// copy from mesh layer
|
||||||
|
std::unique_ptr<QgsSymbol> mTriangularMeshSymbol = nullptr;
|
||||||
|
|
||||||
|
// rendering context
|
||||||
|
QgsRenderContext &mContext;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // QGSMESHLAYERRENDERER_H
|
169
src/core/mesh/qgsmeshmemorydataprovider.cpp
Normal file
169
src/core/mesh/qgsmeshmemorydataprovider.cpp
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmeshmemorydataprovider.cpp
|
||||||
|
-----------------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
///@cond PRIVATE
|
||||||
|
|
||||||
|
#include "qgsmeshmemorydataprovider.h"
|
||||||
|
|
||||||
|
static const QString TEXT_PROVIDER_KEY = QStringLiteral( "mesh_memory" );
|
||||||
|
static const QString TEXT_PROVIDER_DESCRIPTION = QStringLiteral( "Mesh memory provider" );
|
||||||
|
|
||||||
|
bool QgsMeshMemoryDataProvider::isValid() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMeshMemoryDataProvider::name() const
|
||||||
|
{
|
||||||
|
return TEXT_PROVIDER_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMeshMemoryDataProvider::description() const
|
||||||
|
{
|
||||||
|
return TEXT_PROVIDER_DESCRIPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystem QgsMeshMemoryDataProvider::crs() const
|
||||||
|
{
|
||||||
|
return QgsCoordinateReferenceSystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshMemoryDataProvider::QgsMeshMemoryDataProvider( const QString &uri )
|
||||||
|
: QgsMeshDataProvider( uri )
|
||||||
|
{
|
||||||
|
mIsValid = splitSections( uri );
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshMemoryDataProvider::~QgsMeshMemoryDataProvider()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMeshMemoryDataProvider::providerKey()
|
||||||
|
{
|
||||||
|
return TEXT_PROVIDER_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMeshMemoryDataProvider::providerDescription()
|
||||||
|
{
|
||||||
|
return TEXT_PROVIDER_DESCRIPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshMemoryDataProvider *QgsMeshMemoryDataProvider::createProvider( const QString &uri )
|
||||||
|
{
|
||||||
|
return new QgsMeshMemoryDataProvider( uri );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsMeshMemoryDataProvider::splitSections( const QString &uri )
|
||||||
|
{
|
||||||
|
const QStringList sections = uri.split( QStringLiteral( "---" ), QString::SkipEmptyParts );
|
||||||
|
if ( sections.size() != 2 )
|
||||||
|
{
|
||||||
|
setError( QgsError( QStringLiteral( "Invalid mesh definition, does not contain 2 sections" ),
|
||||||
|
QStringLiteral( "Mesh Memory Provider" ) ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( addVertices( sections[0] ) )
|
||||||
|
return addFaces( sections[1] );
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsMeshMemoryDataProvider::addVertices( const QString &def )
|
||||||
|
{
|
||||||
|
QVector<QgsMeshVertex> vertices;
|
||||||
|
|
||||||
|
const QStringList verticesCoords = def.split( '\n', QString::SkipEmptyParts );
|
||||||
|
for ( int i = 0; i < verticesCoords.size(); ++i )
|
||||||
|
{
|
||||||
|
const QStringList coords = verticesCoords[i].split( ',', QString::SkipEmptyParts );
|
||||||
|
if ( coords.size() != 2 )
|
||||||
|
{
|
||||||
|
setError( QgsError( QStringLiteral( "Invalid mesh definition, vertex definition does not contain x, y" ),
|
||||||
|
QStringLiteral( "Mesh Memory Provider" ) ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
double x = coords.at( 0 ).toDouble();
|
||||||
|
double y = coords.at( 1 ).toDouble();
|
||||||
|
QgsMeshVertex vertex( x, y );
|
||||||
|
vertices.push_back( vertex );
|
||||||
|
}
|
||||||
|
|
||||||
|
mVertices = vertices;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsMeshMemoryDataProvider::addFaces( const QString &def )
|
||||||
|
{
|
||||||
|
QVector<QgsMeshFace> faces;
|
||||||
|
|
||||||
|
const QStringList facesVertices = def.split( '\n', QString::SkipEmptyParts );
|
||||||
|
for ( int i = 0; i < facesVertices.size(); ++i )
|
||||||
|
{
|
||||||
|
const QStringList vertices = facesVertices[i].split( ',', QString::SkipEmptyParts );
|
||||||
|
if ( vertices.size() < 3 )
|
||||||
|
{
|
||||||
|
setError( QgsError( QStringLiteral( "Invalid mesh definition, face must contain at least 3 vertices" ),
|
||||||
|
QStringLiteral( "Mesh Memory Provider" ) ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QgsMeshFace face;
|
||||||
|
for ( int j = 0; j < vertices.size(); ++j )
|
||||||
|
{
|
||||||
|
int vertex_id = vertices[j].toInt();
|
||||||
|
if ( vertex_id < 0 )
|
||||||
|
{
|
||||||
|
setError( QgsError( QStringLiteral( "Invalid mesh definition, vertex index must be positive value" ), QStringLiteral( "Mesh Memory Provider" ) ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( mVertices.size() < vertex_id )
|
||||||
|
{
|
||||||
|
setError( QgsError( QStringLiteral( "Invalid mesh definition, missing vertex id defined in face" ), QStringLiteral( "Mesh Memory Provider" ) ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
face.push_back( vertex_id );
|
||||||
|
}
|
||||||
|
faces.push_back( face );
|
||||||
|
}
|
||||||
|
|
||||||
|
mFaces = faces;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsMeshMemoryDataProvider::vertexCount() const
|
||||||
|
{
|
||||||
|
return mVertices.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsMeshMemoryDataProvider::faceCount() const
|
||||||
|
{
|
||||||
|
return mFaces.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshVertex QgsMeshMemoryDataProvider::vertex( int index ) const
|
||||||
|
{
|
||||||
|
Q_ASSERT( vertexCount() > index );
|
||||||
|
return mVertices[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshFace QgsMeshMemoryDataProvider::face( int index ) const
|
||||||
|
{
|
||||||
|
Q_ASSERT( faceCount() > index );
|
||||||
|
return mFaces[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
///@endcond
|
98
src/core/mesh/qgsmeshmemorydataprovider.h
Normal file
98
src/core/mesh/qgsmeshmemorydataprovider.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmeshmemorydataprovider.h
|
||||||
|
---------------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QGSMESHMEMORYDATAPROVIDER_H
|
||||||
|
#define QGSMESHMEMORYDATAPROVIDER_H
|
||||||
|
|
||||||
|
#define SIP_NO_FILE
|
||||||
|
|
||||||
|
///@cond PRIVATE
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "qgis_core.h"
|
||||||
|
#include "qgis.h"
|
||||||
|
#include "qgsmeshdataprovider.h"
|
||||||
|
#include "qgsrectangle.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
* Provides data stored in-memory for QgsMeshLayer. Useful for plugins or tests.
|
||||||
|
* \since QGIS 3.2
|
||||||
|
*/
|
||||||
|
class QgsMeshMemoryDataProvider: public QgsMeshDataProvider
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a mesh in-memory data provider from data string
|
||||||
|
*
|
||||||
|
* Data string constains simple definition of vertices and faces
|
||||||
|
* Each entry is separated by "\n" sign and section deliminer "---"
|
||||||
|
* vertex is x and y coordinate separated by comma
|
||||||
|
* face is list of vertex indexes, numbered from 0
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* QString uri(
|
||||||
|
* "1.0, 2.0 \n" \
|
||||||
|
* "2.0, 2.0 \n" \
|
||||||
|
* "3.0, 2.0 \n" \
|
||||||
|
* "2.0, 3.0 \n" \
|
||||||
|
* "1.0, 3.0 \n" \
|
||||||
|
* "---"
|
||||||
|
* "0, 1, 3, 4 \n" \
|
||||||
|
* "1, 2, 3 \n"
|
||||||
|
* );
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
QgsMeshMemoryDataProvider( const QString &uri = QString() );
|
||||||
|
~QgsMeshMemoryDataProvider();
|
||||||
|
|
||||||
|
bool isValid() const override;
|
||||||
|
QString name() const override;
|
||||||
|
QString description() const override;
|
||||||
|
QgsCoordinateReferenceSystem crs() const override;
|
||||||
|
|
||||||
|
int vertexCount() const override;
|
||||||
|
int faceCount() const override;
|
||||||
|
QgsMeshVertex vertex( int index ) const override;
|
||||||
|
QgsMeshFace face( int index ) const override;
|
||||||
|
|
||||||
|
//! Returns the memory provider key
|
||||||
|
static QString providerKey();
|
||||||
|
//! Returns the memory provider description
|
||||||
|
static QString providerDescription();
|
||||||
|
//! Provider factory
|
||||||
|
static QgsMeshMemoryDataProvider *createProvider( const QString &uri );
|
||||||
|
private:
|
||||||
|
bool splitSections( const QString &uri );
|
||||||
|
|
||||||
|
bool addVertices( const QString &def );
|
||||||
|
bool addFaces( const QString &def );
|
||||||
|
|
||||||
|
QVector<QgsMeshVertex> mVertices;
|
||||||
|
QVector<QgsMeshFace> mFaces;
|
||||||
|
|
||||||
|
bool mIsValid = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
///@endcond
|
||||||
|
|
||||||
|
#endif // QGSMESHMEMORYDATAPROVIDER_H
|
98
src/core/mesh/qgstriangularmesh.cpp
Normal file
98
src/core/mesh/qgstriangularmesh.cpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgstriangularmesh.cpp
|
||||||
|
---------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "qgstriangularmesh.h"
|
||||||
|
#include "qgsrendercontext.h"
|
||||||
|
#include "qgscoordinatetransform.h"
|
||||||
|
|
||||||
|
void QgsTriangularMesh::update( QgsMesh *nativeMesh, QgsRenderContext *context )
|
||||||
|
{
|
||||||
|
Q_ASSERT( nativeMesh );
|
||||||
|
Q_ASSERT( context );
|
||||||
|
|
||||||
|
mTriangularMesh.vertices.clear();
|
||||||
|
mTriangularMesh.faces.clear();
|
||||||
|
mTrianglesToNativeFaces.clear();
|
||||||
|
|
||||||
|
// TRANSFORM VERTICES
|
||||||
|
QgsCoordinateTransform transform = context->coordinateTransform();
|
||||||
|
mTriangularMesh.vertices.resize( nativeMesh->vertices.size() );
|
||||||
|
for ( int i = 0; i < nativeMesh->vertices.size(); ++i )
|
||||||
|
{
|
||||||
|
const QgsMeshVertex &vertex = nativeMesh->vertices.at( i );
|
||||||
|
if ( transform.isValid() )
|
||||||
|
{
|
||||||
|
QgsPointXY mapPoint = transform.transform( QgsPointXY( vertex.x(), vertex.y() ) );
|
||||||
|
QgsMeshVertex mapVertex( mapPoint );
|
||||||
|
mapVertex.setZ( vertex.z() );
|
||||||
|
mapVertex.setM( vertex.m() );
|
||||||
|
mTriangularMesh.vertices[i] = mapVertex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mTriangularMesh.vertices[i] = vertex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CREATE TRIANGULAR MESH
|
||||||
|
for ( int i = 0; i < nativeMesh->faces.size(); ++i )
|
||||||
|
{
|
||||||
|
const QgsMeshFace &face = nativeMesh->faces.at( i ) ;
|
||||||
|
if ( face.size() == 3 )
|
||||||
|
{
|
||||||
|
// triangle
|
||||||
|
mTriangularMesh.faces.push_back( face );
|
||||||
|
mTrianglesToNativeFaces.push_back( i );
|
||||||
|
}
|
||||||
|
else if ( face.size() == 4 )
|
||||||
|
{
|
||||||
|
// quad
|
||||||
|
QgsMeshFace face1;
|
||||||
|
face1.push_back( face[0] );
|
||||||
|
face1.push_back( face[1] );
|
||||||
|
face1.push_back( face[2] );
|
||||||
|
|
||||||
|
mTriangularMesh.faces.push_back( face1 );
|
||||||
|
mTrianglesToNativeFaces.push_back( i );
|
||||||
|
|
||||||
|
QgsMeshFace face2;
|
||||||
|
face2.push_back( face[0] );
|
||||||
|
face2.push_back( face[2] );
|
||||||
|
face2.push_back( face[3] );
|
||||||
|
|
||||||
|
mTriangularMesh.faces.push_back( face2 );
|
||||||
|
mTrianglesToNativeFaces.push_back( i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector<QgsMeshVertex> &QgsTriangularMesh::vertices() const
|
||||||
|
{
|
||||||
|
return mTriangularMesh.vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector<QgsMeshFace> &QgsTriangularMesh::triangles() const
|
||||||
|
{
|
||||||
|
return mTriangularMesh.faces;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector<int> &QgsTriangularMesh::trianglesToNativeFaces() const
|
||||||
|
{
|
||||||
|
return mTrianglesToNativeFaces;
|
||||||
|
}
|
||||||
|
|
82
src/core/mesh/qgstriangularmesh.h
Normal file
82
src/core/mesh/qgstriangularmesh.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgstriangularmesh.h
|
||||||
|
-------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QGSTRIANGULARMESH_H
|
||||||
|
#define QGSTRIANGULARMESH_H
|
||||||
|
|
||||||
|
|
||||||
|
#define SIP_NO_FILE
|
||||||
|
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
#include "qgis_core.h"
|
||||||
|
#include "qgsmeshdataprovider.h"
|
||||||
|
|
||||||
|
class QgsRenderContext;
|
||||||
|
|
||||||
|
//! Mesh - vertices and faces
|
||||||
|
struct CORE_EXPORT QgsMesh
|
||||||
|
{
|
||||||
|
//! vertices
|
||||||
|
QVector<QgsMeshVertex> vertices;
|
||||||
|
//! faces
|
||||||
|
QVector<QgsMeshFace> faces;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup core
|
||||||
|
*
|
||||||
|
* Triangular/Derived Mesh
|
||||||
|
*
|
||||||
|
* \since QGIS 3.2
|
||||||
|
*/
|
||||||
|
class CORE_EXPORT QgsTriangularMesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! Ctor
|
||||||
|
QgsTriangularMesh() = default;
|
||||||
|
//! Dtor
|
||||||
|
~QgsTriangularMesh() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct triangular mesh from layer's native mesh and context
|
||||||
|
* \param nativeMesh QgsMesh to access native vertices and faces
|
||||||
|
* \param context Rendering context to estimate number of triagles to create for an face
|
||||||
|
*/
|
||||||
|
void update( QgsMesh *nativeMesh, QgsRenderContext *context );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return vertices in map CRS
|
||||||
|
*
|
||||||
|
* The list of consist of vertices from native mesh (0-N) and
|
||||||
|
* extra vertices needed to create triangles (N+1 - len)
|
||||||
|
*/
|
||||||
|
const QVector<QgsMeshVertex> &vertices() const ;
|
||||||
|
//! Return triangles
|
||||||
|
const QVector<QgsMeshFace> &triangles() const ;
|
||||||
|
//! Return mapping between triangles and original faces
|
||||||
|
const QVector<int> &trianglesToNativeFaces() const ;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// vertices: map CRS; 0-N ... native vertices, N+1 - len ... extra vertices
|
||||||
|
// faces are derived triangles
|
||||||
|
QgsMesh mTriangularMesh;
|
||||||
|
QVector<int> mTrianglesToNativeFaces; //len(mTrianglesToNativeFaces) == len(mTriangles). Mapping derived -> native
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // QGSTRIANGULARMESH_H
|
@ -111,6 +111,8 @@ QgsMapLayer *QgsProcessingUtils::mapLayerFromStore( const QString &string, QgsMa
|
|||||||
return !canUseLayer( qobject_cast< QgsRasterLayer * >( layer ) );
|
return !canUseLayer( qobject_cast< QgsRasterLayer * >( layer ) );
|
||||||
case QgsMapLayer::PluginLayer:
|
case QgsMapLayer::PluginLayer:
|
||||||
return true;
|
return true;
|
||||||
|
case QgsMapLayer::MeshLayer:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} ), layers.end() );
|
} ), layers.end() );
|
||||||
|
@ -74,6 +74,11 @@ QIcon QgsLayerItem::iconRaster()
|
|||||||
return QgsApplication::getThemeIcon( QStringLiteral( "/mIconRaster.svg" ) );
|
return QgsApplication::getThemeIcon( QStringLiteral( "/mIconRaster.svg" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QIcon QgsLayerItem::iconMesh()
|
||||||
|
{
|
||||||
|
return QgsApplication::getThemeIcon( QStringLiteral( "/mIconPointLayer.svg" ) );
|
||||||
|
}
|
||||||
|
|
||||||
QIcon QgsLayerItem::iconDefault()
|
QIcon QgsLayerItem::iconDefault()
|
||||||
{
|
{
|
||||||
return QgsApplication::getThemeIcon( QStringLiteral( "/mIconLayer.png" ) );
|
return QgsApplication::getThemeIcon( QStringLiteral( "/mIconLayer.png" ) );
|
||||||
@ -602,6 +607,8 @@ QgsMapLayer::LayerType QgsLayerItem::mapLayerType() const
|
|||||||
{
|
{
|
||||||
if ( mLayerType == QgsLayerItem::Raster )
|
if ( mLayerType == QgsLayerItem::Raster )
|
||||||
return QgsMapLayer::RasterLayer;
|
return QgsMapLayer::RasterLayer;
|
||||||
|
if ( mLayerType == QgsLayerItem::Mesh )
|
||||||
|
return QgsMapLayer::MeshLayer;
|
||||||
if ( mLayerType == QgsLayerItem::Plugin )
|
if ( mLayerType == QgsLayerItem::Plugin )
|
||||||
return QgsMapLayer::PluginLayer;
|
return QgsMapLayer::PluginLayer;
|
||||||
return QgsMapLayer::VectorLayer;
|
return QgsMapLayer::VectorLayer;
|
||||||
@ -637,6 +644,8 @@ QString QgsLayerItem::iconName( QgsLayerItem::LayerType layerType )
|
|||||||
case Raster:
|
case Raster:
|
||||||
return QStringLiteral( "/mIconRaster.svg" );
|
return QStringLiteral( "/mIconRaster.svg" );
|
||||||
break;
|
break;
|
||||||
|
case Mesh:
|
||||||
|
//TODO add icon!
|
||||||
default:
|
default:
|
||||||
return QStringLiteral( "/mIconLayer.png" );
|
return QStringLiteral( "/mIconLayer.png" );
|
||||||
break;
|
break;
|
||||||
@ -670,6 +679,9 @@ QgsMimeDataUtils::Uri QgsLayerItem::mimeUri() const
|
|||||||
case QgsMapLayer::RasterLayer:
|
case QgsMapLayer::RasterLayer:
|
||||||
u.layerType = QStringLiteral( "raster" );
|
u.layerType = QStringLiteral( "raster" );
|
||||||
break;
|
break;
|
||||||
|
case QgsMapLayer::MeshLayer:
|
||||||
|
u.layerType = QStringLiteral( "mesh" );
|
||||||
|
break;
|
||||||
case QgsMapLayer::PluginLayer:
|
case QgsMapLayer::PluginLayer:
|
||||||
u.layerType = QStringLiteral( "plugin" );
|
u.layerType = QStringLiteral( "plugin" );
|
||||||
break;
|
break;
|
||||||
|
@ -422,7 +422,8 @@ class CORE_EXPORT QgsLayerItem : public QgsDataItem
|
|||||||
TableLayer,
|
TableLayer,
|
||||||
Database,
|
Database,
|
||||||
Table,
|
Table,
|
||||||
Plugin //!< Added in 2.10
|
Plugin, //!< Added in 2.10
|
||||||
|
Mesh //!< Added in 3.2
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_ENUM( LayerType );
|
Q_ENUM( LayerType );
|
||||||
@ -498,6 +499,8 @@ class CORE_EXPORT QgsLayerItem : public QgsDataItem
|
|||||||
static QIcon iconTable();
|
static QIcon iconTable();
|
||||||
static QIcon iconRaster();
|
static QIcon iconRaster();
|
||||||
static QIcon iconDefault();
|
static QIcon iconDefault();
|
||||||
|
//! Return icon for mesh layer type
|
||||||
|
static QIcon iconMesh();
|
||||||
|
|
||||||
//! \returns the layer name
|
//! \returns the layer name
|
||||||
virtual QString layerName() const { return name(); }
|
virtual QString layerName() const { return name(); }
|
||||||
|
@ -59,6 +59,10 @@ class CORE_EXPORT QgsDataProvider : public QObject
|
|||||||
{
|
{
|
||||||
sipType = sipType_QgsRasterDataProvider;
|
sipType = sipType_QgsRasterDataProvider;
|
||||||
}
|
}
|
||||||
|
else if ( qobject_cast<QgsMeshDataProvider *>( sipCpp ) )
|
||||||
|
{
|
||||||
|
sipType = sipType_QgsMeshDataProvider;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sipType = 0;
|
sipType = 0;
|
||||||
|
@ -85,6 +85,9 @@ class CORE_EXPORT QgsMapLayer : public QObject
|
|||||||
case QgsMapLayer::PluginLayer:
|
case QgsMapLayer::PluginLayer:
|
||||||
sipType = sipType_QgsPluginLayer;
|
sipType = sipType_QgsPluginLayer;
|
||||||
break;
|
break;
|
||||||
|
case QgsMapLayer::MeshLayer:
|
||||||
|
sipType = sipType_QgsMeshLayer;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
sipType = nullptr;
|
sipType = nullptr;
|
||||||
break;
|
break;
|
||||||
@ -100,7 +103,8 @@ class CORE_EXPORT QgsMapLayer : public QObject
|
|||||||
{
|
{
|
||||||
VectorLayer,
|
VectorLayer,
|
||||||
RasterLayer,
|
RasterLayer,
|
||||||
PluginLayer
|
PluginLayer,
|
||||||
|
MeshLayer //!< Added in 3.2
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -359,6 +359,11 @@ QIcon QgsMapLayerModel::iconForLayer( QgsMapLayer *layer )
|
|||||||
return QgsLayerItem::iconRaster();
|
return QgsLayerItem::iconRaster();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case QgsMapLayer::MeshLayer:
|
||||||
|
{
|
||||||
|
return QgsLayerItem::iconMesh();
|
||||||
|
}
|
||||||
|
|
||||||
case QgsMapLayer::VectorLayer:
|
case QgsMapLayer::VectorLayer:
|
||||||
{
|
{
|
||||||
QgsVectorLayer *vl = dynamic_cast<QgsVectorLayer *>( layer );
|
QgsVectorLayer *vl = dynamic_cast<QgsVectorLayer *>( layer );
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "qgsrasterlayer.h"
|
#include "qgsrasterlayer.h"
|
||||||
#include "qgsvectordataprovider.h"
|
#include "qgsvectordataprovider.h"
|
||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
|
#include "qgsmeshlayer.h"
|
||||||
|
|
||||||
static const char *QGIS_URILIST_MIMETYPE = "application/x-vnd.qgis.qgis.uri";
|
static const char *QGIS_URILIST_MIMETYPE = "application/x-vnd.qgis.qgis.uri";
|
||||||
|
|
||||||
@ -108,6 +109,18 @@ QgsRasterLayer *QgsMimeDataUtils::Uri::rasterLayer( bool &owner, QString &error
|
|||||||
return new QgsRasterLayer( uri, name, providerKey );
|
return new QgsRasterLayer( uri, name, providerKey );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsMeshLayer *QgsMimeDataUtils::Uri::meshLayer( bool &owner, QString &error ) const
|
||||||
|
{
|
||||||
|
owner = false;
|
||||||
|
if ( layerType != QLatin1String( "mesh" ) )
|
||||||
|
{
|
||||||
|
error = QObject::tr( "%1: Not a mesh layer." ).arg( name );
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
owner = true;
|
||||||
|
return new QgsMeshLayer( uri, name, providerKey );
|
||||||
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
bool QgsMimeDataUtils::isUriList( const QMimeData *data )
|
bool QgsMimeDataUtils::isUriList( const QMimeData *data )
|
||||||
|
@ -24,6 +24,7 @@ class QgsLayerItem;
|
|||||||
class QgsLayerTreeNode;
|
class QgsLayerTreeNode;
|
||||||
class QgsVectorLayer;
|
class QgsVectorLayer;
|
||||||
class QgsRasterLayer;
|
class QgsRasterLayer;
|
||||||
|
class QgsMeshLayer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup core
|
* \ingroup core
|
||||||
@ -63,7 +64,14 @@ class CORE_EXPORT QgsMimeDataUtils
|
|||||||
*/
|
*/
|
||||||
QgsRasterLayer *rasterLayer( bool &owner, QString &error ) const;
|
QgsRasterLayer *rasterLayer( bool &owner, QString &error ) const;
|
||||||
|
|
||||||
//! Type of URI. Recognized types: "vector" / "raster" / "plugin" / "custom" / "project"
|
/**
|
||||||
|
* Get mesh layer from uri if possible, otherwise returns 0 and error is set
|
||||||
|
* \param owner set to true if caller becomes owner
|
||||||
|
* \param error set to error message if cannot get raster
|
||||||
|
*/
|
||||||
|
QgsMeshLayer *meshLayer( bool &owner, QString &error ) const;
|
||||||
|
|
||||||
|
//! Type of URI. Recognized types: "vector" / "raster" / "mesh" / "plugin" / "custom" / "project"
|
||||||
QString layerType;
|
QString layerType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
#include "qgsproject.h"
|
#include "qgsproject.h"
|
||||||
#include "providers/memory/qgsmemoryprovider.h"
|
#include "providers/memory/qgsmemoryprovider.h"
|
||||||
|
#include "mesh/qgsmeshmemorydataprovider.h"
|
||||||
|
|
||||||
// typedefs for provider plugin functions of interest
|
// typedefs for provider plugin functions of interest
|
||||||
typedef QString providerkey_t();
|
typedef QString providerkey_t();
|
||||||
@ -87,6 +87,7 @@ void QgsProviderRegistry::init()
|
|||||||
{
|
{
|
||||||
// add standard providers
|
// add standard providers
|
||||||
mProviders[ QgsMemoryProvider::providerKey() ] = new QgsProviderMetadata( QgsMemoryProvider::providerKey(), QgsMemoryProvider::providerDescription(), &QgsMemoryProvider::createProvider );
|
mProviders[ QgsMemoryProvider::providerKey() ] = new QgsProviderMetadata( QgsMemoryProvider::providerKey(), QgsMemoryProvider::providerDescription(), &QgsMemoryProvider::createProvider );
|
||||||
|
mProviders[ QgsMeshMemoryDataProvider::providerKey() ] = new QgsProviderMetadata( QgsMeshMemoryDataProvider::providerKey(), QgsMeshMemoryDataProvider::providerDescription(), &QgsMeshMemoryDataProvider::createProvider );
|
||||||
|
|
||||||
mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
|
mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
|
||||||
mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );
|
mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );
|
||||||
|
@ -167,6 +167,7 @@ class CORE_EXPORT QgsProviderRegistry
|
|||||||
\note This replaces QgsRasterLayer::buildSupportedRasterFileFilter()
|
\note This replaces QgsRasterLayer::buildSupportedRasterFileFilter()
|
||||||
*/
|
*/
|
||||||
virtual QString fileRasterFilters() const;
|
virtual QString fileRasterFilters() const;
|
||||||
|
|
||||||
//! Return a string containing the available database drivers
|
//! Return a string containing the available database drivers
|
||||||
virtual QString databaseDrivers() const;
|
virtual QString databaseDrivers() const;
|
||||||
//! Return a string containing the available directory drivers
|
//! Return a string containing the available directory drivers
|
||||||
|
@ -890,6 +890,7 @@ INCLUDE_DIRECTORIES(
|
|||||||
${CMAKE_SOURCE_DIR}/src/core/locator
|
${CMAKE_SOURCE_DIR}/src/core/locator
|
||||||
${CMAKE_SOURCE_DIR}/src/core/metadata
|
${CMAKE_SOURCE_DIR}/src/core/metadata
|
||||||
${CMAKE_SOURCE_DIR}/src/core/processing
|
${CMAKE_SOURCE_DIR}/src/core/processing
|
||||||
|
${CMAKE_SOURCE_DIR}/src/core/mesh
|
||||||
${CMAKE_SOURCE_DIR}/src/core/providers/memory
|
${CMAKE_SOURCE_DIR}/src/core/providers/memory
|
||||||
${CMAKE_SOURCE_DIR}/src/core/raster
|
${CMAKE_SOURCE_DIR}/src/core/raster
|
||||||
${CMAKE_SOURCE_DIR}/src/core/scalebar
|
${CMAKE_SOURCE_DIR}/src/core/scalebar
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
#include "qgsbrowserdockwidget_p.h"
|
#include "qgsbrowserdockwidget_p.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <QAbstractTextDocumentLayout>
|
#include <QAbstractTextDocumentLayout>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
@ -35,7 +37,7 @@
|
|||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
#include "qgsproject.h"
|
#include "qgsproject.h"
|
||||||
#include "qgssettings.h"
|
#include "qgssettings.h"
|
||||||
|
#include "qgsmeshlayer.h"
|
||||||
|
|
||||||
#include <QDragEnterEvent>
|
#include <QDragEnterEvent>
|
||||||
|
|
||||||
@ -143,7 +145,20 @@ void QgsBrowserLayerProperties::setItem( QgsDataItem *item )
|
|||||||
{
|
{
|
||||||
QgsDebugMsg( "creating raster layer" );
|
QgsDebugMsg( "creating raster layer" );
|
||||||
// should copy code from addLayer() to split uri ?
|
// should copy code from addLayer() to split uri ?
|
||||||
QgsRasterLayer *layer = new QgsRasterLayer( layerItem->uri(), layerItem->uri(), layerItem->providerKey() );
|
std::unique_ptr<QgsRasterLayer> layer( new QgsRasterLayer( layerItem->uri(), layerItem->uri(), layerItem->providerKey() ) );
|
||||||
|
if ( layer )
|
||||||
|
{
|
||||||
|
if ( layer->isValid() )
|
||||||
|
{
|
||||||
|
layerCrs = layer->crs();
|
||||||
|
layerMetadata = layer->htmlMetadata();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( type == QgsMapLayer::MeshLayer )
|
||||||
|
{
|
||||||
|
QgsDebugMsg( "creating mesh layer" );
|
||||||
|
std::unique_ptr<QgsMeshLayer> layer( new QgsMeshLayer( layerItem->uri(), layerItem->uri(), layerItem->providerKey() ) );
|
||||||
if ( layer )
|
if ( layer )
|
||||||
{
|
{
|
||||||
if ( layer->isValid() )
|
if ( layer->isValid() )
|
||||||
@ -151,13 +166,12 @@ void QgsBrowserLayerProperties::setItem( QgsDataItem *item )
|
|||||||
layerCrs = layer->crs();
|
layerCrs = layer->crs();
|
||||||
layerMetadata = layer->htmlMetadata();
|
layerMetadata = layer->htmlMetadata();
|
||||||
}
|
}
|
||||||
delete layer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( type == QgsMapLayer::VectorLayer )
|
else if ( type == QgsMapLayer::VectorLayer )
|
||||||
{
|
{
|
||||||
QgsDebugMsg( "creating vector layer" );
|
QgsDebugMsg( "creating vector layer" );
|
||||||
QgsVectorLayer *layer = new QgsVectorLayer( layerItem->uri(), layerItem->name(), layerItem->providerKey() );
|
std::unique_ptr<QgsVectorLayer> layer( new QgsVectorLayer( layerItem->uri(), layerItem->name(), layerItem->providerKey() ) );
|
||||||
if ( layer )
|
if ( layer )
|
||||||
{
|
{
|
||||||
if ( layer->isValid() )
|
if ( layer->isValid() )
|
||||||
@ -165,7 +179,6 @@ void QgsBrowserLayerProperties::setItem( QgsDataItem *item )
|
|||||||
layerCrs = layer->crs();
|
layerCrs = layer->crs();
|
||||||
layerMetadata = layer->htmlMetadata();
|
layerMetadata = layer->htmlMetadata();
|
||||||
}
|
}
|
||||||
delete layer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( type == QgsMapLayer::PluginLayer )
|
else if ( type == QgsMapLayer::PluginLayer )
|
||||||
|
@ -16,6 +16,7 @@ ADD_SUBDIRECTORY(wfs)
|
|||||||
ADD_SUBDIRECTORY(spatialite)
|
ADD_SUBDIRECTORY(spatialite)
|
||||||
ADD_SUBDIRECTORY(virtual)
|
ADD_SUBDIRECTORY(virtual)
|
||||||
ADD_SUBDIRECTORY(db2)
|
ADD_SUBDIRECTORY(db2)
|
||||||
|
ADD_SUBDIRECTORY(mdal)
|
||||||
|
|
||||||
IF (WITH_ORACLE)
|
IF (WITH_ORACLE)
|
||||||
ADD_SUBDIRECTORY(oracle)
|
ADD_SUBDIRECTORY(oracle)
|
||||||
|
80
src/providers/mdal/CMakeLists.txt
Normal file
80
src/providers/mdal/CMakeLists.txt
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
SET(MDAL_SRCS
|
||||||
|
qgsmdalprovider.cpp
|
||||||
|
qgsmdaldataitems.cpp
|
||||||
|
)
|
||||||
|
SET(MDAL_MOC_HDRS
|
||||||
|
qgsmdalprovider.h
|
||||||
|
qgsmdaldataitems.h
|
||||||
|
)
|
||||||
|
SET(MDAL_HDRS
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
########################################################
|
||||||
|
# Compile internal MDAL
|
||||||
|
IF (WITH_INTERNAL_MDAL)
|
||||||
|
ADD_DEFINITIONS(-DMDAL_STATIC)
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(
|
||||||
|
${CMAKE_SOURCE_DIR}/external/mdal
|
||||||
|
${CMAKE_SOURCE_DIR}/external/mdal/api
|
||||||
|
)
|
||||||
|
|
||||||
|
SET(MDAL_LIB_SRCS
|
||||||
|
${CMAKE_SOURCE_DIR}/external/mdal/mdal.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/external/mdal/mdal_utils.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/external/mdal/mdal_loader.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/external/mdal/frmts/mdal_2dm.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
SET(MDAL_LIB_HDRS
|
||||||
|
${CMAKE_SOURCE_DIR}/external/mdal/api/mdal.h
|
||||||
|
${CMAKE_SOURCE_DIR}/external/mdal/mdal_utils.hpp
|
||||||
|
${CMAKE_SOURCE_DIR}/external/mdal/mdal_loader.hpp
|
||||||
|
${CMAKE_SOURCE_DIR}/external/mdal/mdal_defines.hpp
|
||||||
|
${CMAKE_SOURCE_DIR}/external/mdal/frmts/mdal_2dm.hpp
|
||||||
|
)
|
||||||
|
|
||||||
|
UNSET(MDAL_LIBRARY)
|
||||||
|
UNSET(MDAL_INCLUDE_DIR)
|
||||||
|
|
||||||
|
ELSE (WITH_INTERNAL_MDAL)
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES (SYSTEM
|
||||||
|
${MDAL_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
ENDIF (WITH_INTERNAL_MDAL)
|
||||||
|
|
||||||
|
########################################################
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES (
|
||||||
|
${CMAKE_SOURCE_DIR}/src/core
|
||||||
|
${CMAKE_SOURCE_DIR}/src/core/mesh
|
||||||
|
${CMAKE_SOURCE_DIR}/src/core/expression
|
||||||
|
${CMAKE_SOURCE_DIR}/src/core/geometry
|
||||||
|
${CMAKE_SOURCE_DIR}/src/core/metadata
|
||||||
|
|
||||||
|
${CMAKE_BINARY_DIR}/src/core
|
||||||
|
)
|
||||||
|
|
||||||
|
QT5_WRAP_CPP(MDAL_MOC_SRCS ${MDAL_MOC_HDRS})
|
||||||
|
ADD_LIBRARY (mdalprovider MODULE ${MDAL_SRCS} ${MDAL_MOC_HDRS} ${MDAL_MOC_SRCS} ${MDAL_LIB_SRCS} ${MDAL_LIB_HDRS})
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES (mdalprovider
|
||||||
|
qgis_core
|
||||||
|
${MDAL_LIBRARY}
|
||||||
|
)
|
||||||
|
|
||||||
|
# clang-tidy
|
||||||
|
IF(CLANG_TIDY_EXE)
|
||||||
|
SET_TARGET_PROPERTIES(
|
||||||
|
mdalprovider PROPERTIES
|
||||||
|
CXX_CLANG_TIDY "${DO_CLANG_TIDY}"
|
||||||
|
)
|
||||||
|
ENDIF(CLANG_TIDY_EXE)
|
||||||
|
|
||||||
|
INSTALL(TARGETS mdalprovider
|
||||||
|
RUNTIME DESTINATION ${QGIS_PLUGIN_DIR}
|
||||||
|
LIBRARY DESTINATION ${QGIS_PLUGIN_DIR})
|
||||||
|
|
76
src/providers/mdal/qgsmdaldataitems.cpp
Normal file
76
src/providers/mdal/qgsmdaldataitems.cpp
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmdaldataitems.cpp
|
||||||
|
---------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "qgsmdaldataitems.h"
|
||||||
|
#include "qgsmdalprovider.h"
|
||||||
|
#include "qgslogger.h"
|
||||||
|
#include "qgssettings.h"
|
||||||
|
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
|
||||||
|
QgsMdalLayerItem::QgsMdalLayerItem( QgsDataItem *parent,
|
||||||
|
const QString &name, const QString &path, const QString &uri )
|
||||||
|
: QgsLayerItem( parent, name, path, uri, QgsLayerItem::Mesh, QStringLiteral( "mdal" ) )
|
||||||
|
{
|
||||||
|
mToolTip = uri;
|
||||||
|
setState( Populated );
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMdalLayerItem::layerName() const
|
||||||
|
{
|
||||||
|
QFileInfo info( name() );
|
||||||
|
return info.completeBaseName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
static QStringList sExtensions = QStringList();
|
||||||
|
|
||||||
|
QGISEXTERN int dataCapabilities()
|
||||||
|
{
|
||||||
|
return QgsDataProvider::File;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
|
||||||
|
{
|
||||||
|
if ( path.isEmpty() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
QgsDebugMsgLevel( "thePath = " + path, 2 );
|
||||||
|
|
||||||
|
// get suffix, removing .gz if present
|
||||||
|
QFileInfo info( path );
|
||||||
|
QString suffix = info.suffix().toLower();
|
||||||
|
// extract basename with extension
|
||||||
|
info.setFile( path );
|
||||||
|
QString name = info.fileName();
|
||||||
|
|
||||||
|
// allow only normal files
|
||||||
|
if ( !info.isFile() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// get supported extensions
|
||||||
|
if ( sExtensions.isEmpty() )
|
||||||
|
{
|
||||||
|
// TODO ask MDAL for extensions !
|
||||||
|
sExtensions << QStringLiteral( "2dm" );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter files by extension
|
||||||
|
if ( !sExtensions.contains( suffix ) )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return new QgsMdalLayerItem( parentItem, name, path, path );
|
||||||
|
}
|
||||||
|
|
31
src/providers/mdal/qgsmdaldataitems.h
Normal file
31
src/providers/mdal/qgsmdaldataitems.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmdaldataitems.h
|
||||||
|
------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef QGSMDALDATAITEMS_H
|
||||||
|
#define QGSMDALDATAITEMS_H
|
||||||
|
|
||||||
|
#include "qgsdataitem.h"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class QgsMdalLayerItem : public QgsLayerItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
QgsMdalLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri );
|
||||||
|
|
||||||
|
QString layerName() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QGSMDALDATAITEMS_H
|
133
src/providers/mdal/qgsmdalprovider.cpp
Normal file
133
src/providers/mdal/qgsmdalprovider.cpp
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmeshmemorydataprovider.cpp
|
||||||
|
-----------------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "qgsmdalprovider.h"
|
||||||
|
|
||||||
|
static const QString TEXT_PROVIDER_KEY = QStringLiteral( "mdal" );
|
||||||
|
static const QString TEXT_PROVIDER_DESCRIPTION = QStringLiteral( "MDAL provider" );
|
||||||
|
|
||||||
|
bool QgsMdalProvider::isValid() const
|
||||||
|
{
|
||||||
|
return mMeshH != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMdalProvider::name() const
|
||||||
|
{
|
||||||
|
return TEXT_PROVIDER_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QgsMdalProvider::description() const
|
||||||
|
{
|
||||||
|
return TEXT_PROVIDER_DESCRIPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystem QgsMdalProvider::crs() const
|
||||||
|
{
|
||||||
|
return QgsCoordinateReferenceSystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMdalProvider::QgsMdalProvider( const QString &uri )
|
||||||
|
: QgsMeshDataProvider( uri )
|
||||||
|
{
|
||||||
|
QByteArray curi = uri.toAscii();
|
||||||
|
mMeshH = MDAL_LoadMesh( curi.constData() );
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMdalProvider::~QgsMdalProvider()
|
||||||
|
{
|
||||||
|
if ( mMeshH )
|
||||||
|
MDAL_CloseMesh( mMeshH );
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsMdalProvider::vertexCount() const
|
||||||
|
{
|
||||||
|
if ( mMeshH )
|
||||||
|
return MDAL_M_vertexCount( mMeshH );
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsMdalProvider::faceCount() const
|
||||||
|
{
|
||||||
|
if ( mMeshH )
|
||||||
|
return MDAL_M_faceCount( mMeshH );
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshVertex QgsMdalProvider::vertex( int index ) const
|
||||||
|
{
|
||||||
|
Q_ASSERT( index < vertexCount() );
|
||||||
|
double x = MDAL_M_vertexXCoordinatesAt( mMeshH, index );
|
||||||
|
double y = MDAL_M_vertexYCoordinatesAt( mMeshH, index );
|
||||||
|
QgsMeshVertex vertex( x, y );
|
||||||
|
return vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsMeshFace QgsMdalProvider::face( int index ) const
|
||||||
|
{
|
||||||
|
Q_ASSERT( index < faceCount() );
|
||||||
|
QgsMeshFace face;
|
||||||
|
int n_face_vertices = MDAL_M_faceVerticesCountAt( mMeshH, index );
|
||||||
|
for ( int j = 0; j < n_face_vertices; ++j )
|
||||||
|
{
|
||||||
|
int vertex_index = MDAL_M_faceVerticesIndexAt( mMeshH, index, j );
|
||||||
|
face.push_back( vertex_index );
|
||||||
|
}
|
||||||
|
return face;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class factory to return a pointer to a newly created
|
||||||
|
* QgsGdalProvider object
|
||||||
|
*/
|
||||||
|
QGISEXTERN QgsMdalProvider *classFactory( const QString *uri )
|
||||||
|
{
|
||||||
|
return new QgsMdalProvider( *uri );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required key function (used to map the plugin to a data store type)
|
||||||
|
*/
|
||||||
|
QGISEXTERN QString providerKey()
|
||||||
|
{
|
||||||
|
return TEXT_PROVIDER_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required description function
|
||||||
|
*/
|
||||||
|
QGISEXTERN QString description()
|
||||||
|
{
|
||||||
|
return TEXT_PROVIDER_DESCRIPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required isProvider function. Used to determine if this shared library
|
||||||
|
* is a data provider plugin
|
||||||
|
*/
|
||||||
|
QGISEXTERN bool isProvider()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGISEXTERN void cleanupProvider()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
63
src/providers/mdal/qgsmdalprovider.h
Normal file
63
src/providers/mdal/qgsmdalprovider.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsmdalprovider.h
|
||||||
|
-----------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QGSMDALPROVIDER_H
|
||||||
|
#define QGSGDALPROVIDER_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <mdal.h>
|
||||||
|
|
||||||
|
#include "qgscoordinatereferencesystem.h"
|
||||||
|
#include "qgsmeshdataprovider.h"
|
||||||
|
|
||||||
|
class QMutex;
|
||||||
|
class QgsCoordinateTransform;
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Data provider for MDAL layers.
|
||||||
|
*/
|
||||||
|
class QgsMdalProvider : public QgsMeshDataProvider
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the provider.
|
||||||
|
*
|
||||||
|
* \param uri file name
|
||||||
|
* \param newDataset handle of newly created dataset.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
QgsMdalProvider( const QString &uri = QString() );
|
||||||
|
~QgsMdalProvider();
|
||||||
|
|
||||||
|
bool isValid() const override;
|
||||||
|
QString name() const override;
|
||||||
|
QString description() const override;
|
||||||
|
QgsCoordinateReferenceSystem crs() const override;
|
||||||
|
|
||||||
|
int vertexCount() const override;
|
||||||
|
int faceCount() const override;
|
||||||
|
QgsMeshVertex vertex( int index ) const override;
|
||||||
|
QgsMeshFace face( int index ) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MeshH mMeshH;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -228,6 +228,12 @@ bool QgsGeoPackageCollectionItem::handleDrop( const QMimeData *data, Qt::DropAct
|
|||||||
srcLayer = dropUri.vectorLayer( owner, error );
|
srcLayer = dropUri.vectorLayer( owner, error );
|
||||||
isVector = true;
|
isVector = true;
|
||||||
}
|
}
|
||||||
|
else if ( dropUri.layerType == QStringLiteral( "mesh" ) )
|
||||||
|
{
|
||||||
|
// unsupported
|
||||||
|
hasError = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
srcLayer = dropUri.rasterLayer( owner, error );
|
srcLayer = dropUri.rasterLayer( owner, error );
|
||||||
|
@ -20,6 +20,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
|
|||||||
${CMAKE_SOURCE_DIR}/src/core/raster
|
${CMAKE_SOURCE_DIR}/src/core/raster
|
||||||
${CMAKE_SOURCE_DIR}/src/core/scalebar
|
${CMAKE_SOURCE_DIR}/src/core/scalebar
|
||||||
${CMAKE_SOURCE_DIR}/src/core/symbology
|
${CMAKE_SOURCE_DIR}/src/core/symbology
|
||||||
|
${CMAKE_SOURCE_DIR}/src/core/mesh
|
||||||
${CMAKE_SOURCE_DIR}/src/test
|
${CMAKE_SOURCE_DIR}/src/test
|
||||||
${CMAKE_BINARY_DIR}/src/core
|
${CMAKE_BINARY_DIR}/src/core
|
||||||
)
|
)
|
||||||
@ -188,7 +189,9 @@ SET(TESTS
|
|||||||
testqgsvectorlayerjoinbuffer.cpp
|
testqgsvectorlayerjoinbuffer.cpp
|
||||||
testqgsvectorlayer.cpp
|
testqgsvectorlayer.cpp
|
||||||
testziplayer.cpp
|
testziplayer.cpp
|
||||||
)
|
testqgsmeshlayer.cpp
|
||||||
|
testqgsmeshlayerrenderer.cpp
|
||||||
|
)
|
||||||
|
|
||||||
IF(WITH_QTWEBKIT)
|
IF(WITH_QTWEBKIT)
|
||||||
SET(TESTS ${TESTS}
|
SET(TESTS ${TESTS}
|
||||||
|
124
tests/src/core/testqgsmeshlayer.cpp
Normal file
124
tests/src/core/testqgsmeshlayer.cpp
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
testqgsmeshlayer.cpp
|
||||||
|
--------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "qgstest.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
//qgis includes...
|
||||||
|
#include "qgsmaplayer.h"
|
||||||
|
#include "qgsmeshlayer.h"
|
||||||
|
#include "qgsapplication.h"
|
||||||
|
#include "qgsproviderregistry.h"
|
||||||
|
#include "qgsproject.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup UnitTests
|
||||||
|
* This is a unit test for a mesh layer
|
||||||
|
*/
|
||||||
|
class TestQgsMeshLayer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TestQgsMeshLayer() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QgsMeshLayer *mMemoryLayer = nullptr;
|
||||||
|
QgsMeshLayer *mMdalLayer = nullptr;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void initTestCase();// will be called before the first testfunction is executed.
|
||||||
|
void cleanupTestCase();// will be called after the last testfunction was executed.
|
||||||
|
void init() {} // will be called before each testfunction is executed.
|
||||||
|
void cleanup() {} // will be called after every testfunction.
|
||||||
|
|
||||||
|
void test_data_provider();
|
||||||
|
void test_extent();
|
||||||
|
};
|
||||||
|
|
||||||
|
void TestQgsMeshLayer::initTestCase()
|
||||||
|
{
|
||||||
|
// init QGIS's paths - true means that all path will be inited from prefix
|
||||||
|
QgsApplication::init();
|
||||||
|
QgsApplication::initQgis();
|
||||||
|
QgsApplication::showSettings();
|
||||||
|
QString myDataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
|
||||||
|
myDataDir += "/mesh";
|
||||||
|
// Memory layer
|
||||||
|
QFile f( myDataDir + "/quad_and_triangle.txt" );
|
||||||
|
QVERIFY( f.open( QIODevice::ReadOnly | QIODevice::Text ) );
|
||||||
|
QString uri( f.readAll() );
|
||||||
|
QVERIFY( !uri.isEmpty() );
|
||||||
|
mMemoryLayer = new QgsMeshLayer( uri, "Triangle and Quad Memory", "mesh_memory" );
|
||||||
|
QVERIFY( mMemoryLayer->isValid() );
|
||||||
|
QgsProject::instance()->addMapLayers(
|
||||||
|
QList<QgsMapLayer *>() << mMemoryLayer );
|
||||||
|
|
||||||
|
// MDAL Layer
|
||||||
|
uri = myDataDir + "/quad_and_triangle.2dm";
|
||||||
|
mMdalLayer = new QgsMeshLayer( uri, "Triangle and Quad MDAL", "mdal" );
|
||||||
|
QVERIFY( mMdalLayer->isValid() );
|
||||||
|
QgsProject::instance()->addMapLayers(
|
||||||
|
QList<QgsMapLayer *>() << mMdalLayer );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsMeshLayer::cleanupTestCase()
|
||||||
|
{
|
||||||
|
QgsApplication::exitQgis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsMeshLayer::test_data_provider()
|
||||||
|
{
|
||||||
|
QList<const QgsMeshDataProvider *> dataProviders;
|
||||||
|
dataProviders.append( mMemoryLayer->dataProvider() );
|
||||||
|
dataProviders.append( mMdalLayer->dataProvider() );
|
||||||
|
|
||||||
|
QgsRectangle expectedExtent( 1000.0, 2000.0, 3000.0, 3000.0 );
|
||||||
|
|
||||||
|
foreach ( auto dp, dataProviders )
|
||||||
|
{
|
||||||
|
QVERIFY( dp != nullptr );
|
||||||
|
QVERIFY( dp->isValid() );
|
||||||
|
QCOMPARE( expectedExtent, dp->extent() );
|
||||||
|
|
||||||
|
QCOMPARE( 5, dp->vertexCount() );
|
||||||
|
QCOMPARE( QgsMeshVertex( 1000.0, 2000.0 ), dp->vertex( 0 ) );
|
||||||
|
QCOMPARE( QgsMeshVertex( 2000.0, 2000.0 ), dp->vertex( 1 ) );
|
||||||
|
QCOMPARE( QgsMeshVertex( 3000.0, 2000.0 ), dp->vertex( 2 ) );
|
||||||
|
QCOMPARE( QgsMeshVertex( 2000.0, 3000.0 ), dp->vertex( 3 ) );
|
||||||
|
QCOMPARE( QgsMeshVertex( 1000.0, 3000.0 ), dp->vertex( 4 ) );
|
||||||
|
|
||||||
|
QCOMPARE( 2, dp->faceCount() );
|
||||||
|
QgsMeshFace f1;
|
||||||
|
f1 << 0 << 1 << 3 << 4;
|
||||||
|
QCOMPARE( f1, dp->face( 0 ) );
|
||||||
|
|
||||||
|
QgsMeshFace f2;
|
||||||
|
f2 << 1 << 2 << 3;
|
||||||
|
QCOMPARE( f2, dp->face( 1 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsMeshLayer::test_extent()
|
||||||
|
{
|
||||||
|
QCOMPARE( mMemoryLayer->dataProvider()->extent(), mMemoryLayer->extent() );
|
||||||
|
QCOMPARE( mMdalLayer->dataProvider()->extent(), mMdalLayer->extent() );
|
||||||
|
}
|
||||||
|
|
||||||
|
QGSTEST_MAIN( TestQgsMeshLayer )
|
||||||
|
#include "testqgsmeshlayer.moc"
|
123
tests/src/core/testqgsmeshlayerrenderer.cpp
Normal file
123
tests/src/core/testqgsmeshlayerrenderer.cpp
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
testqgsmeshlayer.cpp
|
||||||
|
--------------------
|
||||||
|
begin : April 2018
|
||||||
|
copyright : (C) 2018 by Peter Petrik
|
||||||
|
email : zilolv at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "qgstest.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
|
||||||
|
//qgis includes...
|
||||||
|
#include "qgsmaplayer.h"
|
||||||
|
#include "qgsmeshlayer.h"
|
||||||
|
#include "qgsapplication.h"
|
||||||
|
#include "qgsproviderregistry.h"
|
||||||
|
#include "qgsproject.h"
|
||||||
|
#include "qgsmaprenderersequentialjob.h"
|
||||||
|
#include "qgsmeshmemorydataprovider.h"
|
||||||
|
|
||||||
|
//qgis test includes
|
||||||
|
#include "qgsrenderchecker.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \ingroup UnitTests
|
||||||
|
* This is a unit test for the different renderers for mesh layers.
|
||||||
|
*/
|
||||||
|
class TestQgsMeshRenderer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TestQgsMeshRenderer() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QgsMeshLayer *mMemoryLayer = nullptr;
|
||||||
|
QgsMapSettings *mMapSettings = nullptr;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void initTestCase();// will be called before the first testfunction is executed.
|
||||||
|
void cleanupTestCase();// will be called after the last testfunction was executed.
|
||||||
|
void init() {} // will be called before each testfunction is executed.
|
||||||
|
void cleanup() {} // will be called after every testfunction.
|
||||||
|
bool imageCheck( const QString &testType );
|
||||||
|
|
||||||
|
void test_native_mesh_rendering();
|
||||||
|
void test_triangular_mesh_rendering();
|
||||||
|
};
|
||||||
|
|
||||||
|
void TestQgsMeshRenderer::initTestCase()
|
||||||
|
{
|
||||||
|
// init QGIS's paths - true means that all path will be inited from prefix
|
||||||
|
QgsApplication::init();
|
||||||
|
QgsApplication::initQgis();
|
||||||
|
QgsApplication::showSettings();
|
||||||
|
QString myDataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
|
||||||
|
myDataDir += "/mesh";
|
||||||
|
|
||||||
|
mMapSettings = new QgsMapSettings();
|
||||||
|
|
||||||
|
// Memory layer
|
||||||
|
QFile f( myDataDir + "/quad_and_triangle.txt" );
|
||||||
|
QVERIFY( f.open( QIODevice::ReadOnly | QIODevice::Text ) );
|
||||||
|
QString uri( f.readAll() );
|
||||||
|
QVERIFY( !uri.isEmpty() );
|
||||||
|
mMemoryLayer = new QgsMeshLayer( uri, "Triangle and Quad Memory", "mesh_memory" );
|
||||||
|
QVERIFY( mMemoryLayer->isValid() );
|
||||||
|
QgsProject::instance()->addMapLayers(
|
||||||
|
QList<QgsMapLayer *>() << mMemoryLayer );
|
||||||
|
mMapSettings->setLayers(
|
||||||
|
QList<QgsMapLayer *>() << mMemoryLayer );
|
||||||
|
}
|
||||||
|
void TestQgsMeshRenderer::cleanupTestCase()
|
||||||
|
{
|
||||||
|
QgsApplication::exitQgis();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestQgsMeshRenderer::imageCheck( const QString &testType )
|
||||||
|
{
|
||||||
|
mMapSettings->setExtent( mMemoryLayer->extent() );
|
||||||
|
mMapSettings->setDestinationCrs( mMemoryLayer->crs() );
|
||||||
|
mMapSettings->setOutputDpi( 96 );
|
||||||
|
QgsRenderChecker myChecker;
|
||||||
|
myChecker.setControlPathPrefix( QStringLiteral( "mesh" ) );
|
||||||
|
myChecker.setControlName( "expected_" + testType );
|
||||||
|
myChecker.setMapSettings( *mMapSettings );
|
||||||
|
myChecker.setColorTolerance( 15 );
|
||||||
|
bool myResultFlag = myChecker.runTest( testType, 0 );
|
||||||
|
return myResultFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsMeshRenderer::test_native_mesh_rendering()
|
||||||
|
{
|
||||||
|
mMemoryLayer->toggleTriangularMeshRendering( false );
|
||||||
|
QVERIFY( mMemoryLayer->triangularMeshSymbol() == nullptr );
|
||||||
|
QVERIFY( imageCheck( "quad_and_triangle_native_mesh" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestQgsMeshRenderer::test_triangular_mesh_rendering()
|
||||||
|
{
|
||||||
|
mMemoryLayer->toggleTriangularMeshRendering( true );
|
||||||
|
QVERIFY( mMemoryLayer->triangularMeshSymbol() != nullptr );
|
||||||
|
QVERIFY( imageCheck( "quad_and_triangle_triangular_mesh" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
QGSTEST_MAIN( TestQgsMeshRenderer )
|
||||||
|
#include "testqgsmeshlayerrenderer.moc"
|
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
8
tests/testdata/mesh/quad_and_triangle.2dm
vendored
Normal file
8
tests/testdata/mesh/quad_and_triangle.2dm
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
MESH2D 1000.000 2000.000 0.000000 200 300 1.000 1.000
|
||||||
|
ND 1 1000.000 2000.000 20.000
|
||||||
|
ND 2 2000.000 2000.000 30.000
|
||||||
|
ND 3 3000.000 2000.000 40.000
|
||||||
|
ND 4 2000.000 3000.000 50.000
|
||||||
|
ND 5 1000.000 3000.000 10.000
|
||||||
|
E4Q 1 1 2 4 5 1
|
||||||
|
E3T 2 2 3 4 1
|
8
tests/testdata/mesh/quad_and_triangle.txt
vendored
Normal file
8
tests/testdata/mesh/quad_and_triangle.txt
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
1000.0, 2000.0
|
||||||
|
2000.0, 2000.0
|
||||||
|
3000.0, 2000.0
|
||||||
|
2000.0, 3000.0
|
||||||
|
1000.0, 3000.0
|
||||||
|
---
|
||||||
|
0, 1, 3, 4
|
||||||
|
1, 2, 3
|
Loading…
x
Reference in New Issue
Block a user