qgis / QGIS-Enhancement-Proposals

QEP's (QGIS Enhancement Proposals) are used in the process of creating and discussing new enhancements for QGIS
117 stars 37 forks source link

Mesh Layer Editing #228

Open vcloarec opened 3 years ago

vcloarec commented 3 years ago

QGIS Enhancement: Mesh Layer Editing

Date 2021/06/02

Author Vincent Cloarec (@vcloarec)

Contact vcloarec at gmail dot com

maintainer @vcloarec @PeterPetrik

Version QGIS 3.22

Summary

In QGIS 3.20,it is not possible to edit mesh layer frame (see https://github.com/qgis/QGIS-Enhancement-Proposals/issues/119). The only ways to obtain mesh are:

It is possible to add a new dataset group derived from existing dataset groups but there is no possibility of modifying the mesh frame, adding/moving/removing faces and vertices. Indeed, the interest of mesh editing could be :

This QEP concerns allowing QGIS to edit mesh frame vertices and faces. It doesn't propose to edit 3D stacked meshed nor the 1D meshes (https://github.com/qgis/QGIS-Enhancement-Proposals/issues/164))

Proposed Solution

Start editing a mesh layer

Similarly to vector layers, for editing mesh, users will need to enter in an edit mode in the same way.

But for mesh layers, there could be some dataset groups associated with the mesh frame. Editing the mesh frame would lead to making an inconsistency between the mesh frame and dataset group. So, to avoid this inconsistency, editing mesh will remove all the dataset groups present in the mesh. The user could choose to remove the dataset groups in the current file or write the edited mesh in a new file.

Displaying faces and vertices during editing

Currently, vertices are not displayed in QGIS, only edges of faces can be displayed, and are filled with color depending on the dataset groups.

During editing, vertices will be displayed as the vector layer vertices (red circle) when associated faces will be hovered by the mouse. Free vertices (a free vertex is a vertex that doesn't belong to any face, see below) will always be displayed this way.

Selecting faces and vertices

Selection of face and vertices will be possible as for vector layers during editing vertices:

Other tools will allow to choose vertices or faces in the following way :

Editing tools

For editing mesh, the following tools will be implemented.

Edit vertices

Edit faces

Triangulation

With selected vertices, the user can perform a Delaunay triangulation, creating new faces. Only faces compatible with existing faces will be kept in the mesh. That is, new faces intersecting with existing ones will be removed.

Force break line / structure line by polyline

The user will have the possibility to insert lines that force the mesh to follow the line.

Multi edit by expression

The user could modify the X, Y, Z coordinate of selected vertices by expression.

Implementation

New QgsMeshEditor class

These new features will lead to having an infrastructure supporting mesh modification. This infrastructure has to be able to:

A new class QgsMeshEditor will be implemented. When editing, an instance of this class will be the interface between QgsMeshDataProvider and QgsTriangularMesh, as in the figure below. This new class will be responsible for all editing operations on the mesh frame and synchronizing mesh with the QgsTriangularMesh during editing and with QgsMeshDataProvider when changes are committed.

This new class QgsMeshEditor will be owned by the mesh layer during editing and exposed in the CORE API to allow access from the QGIS application. For triangulation (or later, for other mesh generation), the QgsMeshEditor instance will need triangulation algorithms from the ANALYSIS API. Access to mesh generation algorithms will be done through a new abstract interface QgsMeshGenerator that could generate the entire mesh or part of the mesh depending on the elements. Derived classes of QgsMeshGenerator could be implemented in the ANALYSIS API, instantiated in the application, and provided to the QgsMeshEditor for generating part of the mesh.

This organization will allow, in the future, new mesh generators implemented in the ANALYSIS API.

Internal edit action in the QgsMeshEditor class

Edition of the mesh frame will be a succession of edit actions on a QgsMesh own by the instance of QgsMeshEditor. Each edit action will be contained in QUndoCommand sent in the undo/redo stack, so the user will be able to undo/redo edition.

To keep consistency between:

all faces and vertices have to keep the same place in the container during all the editions, even the deleted element.

So during edition of the mesh frame:

The diagram below describes possible edit actions associated with the resulting internal mesh and information to store for the undo/redo mechanism.

Interaction between QgsMeshEditor and QgsTriangularMesh

The class that allows rendering of the mesh is the QgsTriangulatMesh. This class is a discretization of the native mesh following the principle below:

The particularities of this current implementation are:

To avoid reconstructing all the triangular mesh for each edit action, it is possible to update locally the triangular mesh as in diagrams below for different edit actions.

Spatial index

With QGIS 3.20 mesh spatial index is built when constructing the triangular mesh and not updated as the triangular mesh does not change during the life of the mesh layer. So this spatial index supports only creation and does not support add/remove faces after creation.

To avoid rebuilding all the spatial index, it will be necessary to make it support add/remove faces. For this, it would be quite straightforward to follow the way spatial index is implemented for vector layers.

User interface

The user interface for editing mesh will consist of a toolbar. A draft of how this toolbar could be is presented below. This toolbar will be enabled when a mesh layer in edit mode is selected.

This draft is not the definitive user interface, this is just a drawing to illustrate how the functionalities could be exposed to the user. For example, the line edit widget the Z value could be replaced with a popup widget as, for example,vector layer feature rotation. In this particular case, the user could be able to change the value with a minimum of mouse/keyboard actions.

Affected Files

Most of the files related to the mesh layer in QGIS core.

qgisapp.h / qgisapp.cpp to integrate user interface

Implementation process

The first part of the implementation will be the core part, that is :

This very important part of development will be test driven.

Once the base of this implementation could allow editing the mesh frame consistently, user interface implementation could start with an iterative, incremental and adaptive way.

Votes

nyalldawson commented 3 years ago

@vcloarec exciting stuff!

Can I put in one request before you start developing the interactive edit tools? We need to make sure these follow the same interaction patterns as other map edit tools, i.e:

troopa81 commented 3 years ago

Just wanted to say that the way everything is described and explained in this QEP is outstanding. Great work!

michalkleczek commented 3 years ago

Awesome idea! Perhaps this project where I was invloved can be useful: [https://github.com/Deltares/MeshKernel] I think adding it in the QGis is a very smart move. Good luck!

lucacarniato commented 3 years ago

Nice document. Just a thought: the native faces are represented as a composition of triangles. When executing certain mesh algorithm, one could be interested in accessing native faces proprieties (e.g. the center of mass of a quad) at the lowest level (now represented by the “Triangular mesh”) without using the map triangles-> native. How can this problem be solved?

vcloarec commented 3 years ago

@lucacarniato The triangular mesh is used for displaying and spatial index in the map's system coordinates. Operations (all moving, adding, removing, even complex operations from algorithm) on mesh will be on the native mesh contained in the QgsMeshEditor that contains the layer mesh in layer coordinates (called the native mesh). Native mesh is still the lowest level, but there will be a synchronization of the triangular mesh just after the native mesh operation.

If you need to have access from the triangular mesh to the centroïd or other derived value from faces/vertices: triangular face --> map Triangular to Native --> Native faces --> vertex indexes --> map and layer vertices for the native faces.

lucacarniato commented 2 years ago

Dear Vincent,

In case you have some time, I would like to know your opinion on using Meshkernel for mesh generation in Mesh Layer.

MeshKernel can be used for generating unstructured 2D meshes in polygons, improving unstructured mesh smoothness and orthogonality, generating curvilinear grids using splines (for applications simulating flow in rivers), and for generating connections between 1D networks and 2D meshes (for urban environments). The C API of this library can be found here:

https://github.com/Deltares/MeshKernel/blob/master/include/MeshKernelApi/MeshKernel.hpp

Thank you!

Best regards,

Luca

vcloarec commented 2 years ago

Hi @lucacarniato ,

Sorry for the delay...

I see two possible ways for mesh generation in QGIS:

The first way is maybe the easiest way to implement because we can create a complete new mesh, eventually from another one, and we don't have to handle with existing structure consistency. Indeed, with editing mode, the difficulty is to modify massively and locally the internal mesh structure without breaking it. In mesh editing mode, the mesh internal structure is more complex. It is possible, but more difficult...

I think both are possible to implement through a plugin. There are some existing infrastructures in the core that allow some interaction through plugins. Not sure all are exposed to Python but that would not ask a lot of work if needed.

As your API is in C, it could ask to implement it in the core to be easily cross platform.

On my personal side, right now, I am working on generate/edit mesh frame in interaction with QGIS API to produce hydraulic modeling mesh in a stand alone application. For now, I am using Gmsh library to generate the mesh, but I am thinking of allowing several other mesh generation engines. It is a good way to experiment mesh generation with QGIS environment and maybe to port the logic later in the QGIS application. If you are interested and want to have a look (mesh part is on work in progress): https://github.com/vcloarec/ReosProject

TokyoWarfare commented 1 year ago

If suggestions are accepted, pleas consider this. Be able to clip the mesh so it is cut in several pieces following an user provided grid layer which could be closed polylines, shapes or whatever is more convenient.