Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mesh Layer Editing #228

Open
vcloarec opened this issue Jun 2, 2021 · 8 comments
Open

Mesh Layer Editing #228

vcloarec opened this issue Jun 2, 2021 · 8 comments

Comments

@vcloarec
Copy link
Member

vcloarec commented Jun 2, 2021

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 #119). The only ways to obtain mesh are:

  • Produce result mesh from a specific modeling software.
  • Download mesh data from specific providers.
  • Create TIN mesh with the processing tool "TIN mesh creation."

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 :

  • Create or edit his a DEM TIN mesh (Triangular Irregular Network) by manipulating each vertex and face. This feature could be useful, for example, for construction projects, especially associated with the 3D view.
  • Modelers can create/edit their preprocess meshes directly with QGIS before using it in the solver.

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 (#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:

  • click on face select the face
  • drag a rectangular rubber band containing vertices will select the vertices

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

  • drag a rectangular rubber band for vertices OR faces

  • draw a polygon or select an existing one

  • Selection faces by size (area bigger or smaller than a given area)

  • Selection by expression

Editing tools

For editing mesh, the following tools will be implemented.

Edit vertices

  • Add vertex: the user enters a new vertex with the mouse or enters X, Y, Z coordinates. A non-modal widget with Z coordinate will allow the user to enter the Z value when the mouse is used. If the new vertex is in an existing face, the face will be triangulated accordingly to the new vertex, leading to new faces. If the new vertex is outside any faces, a "free" vertex will be added. A free vertex is a vertex that doesn't belong to any faces.
  • Remove vertex: the user can remove a selected vertex. All faces linked to the vertex are also removed, then there are two possible behaviors: the hole is triangulated to fill it, or the hole stays a hole in the mesh.
  • Move vertex: selected vertex can be moved while the edges of associated faces do not intersect.

Edit faces

  • Add face: by selecting three or more vertices (if supported by file format), the user can add a new face.
  • Remove face: the user can choose a face (or more) to remove. This action will not remove any vertices, and if vertices do not belong anymore to any face, they will become free vertices.
  • Flip faces: the user will be able to flip two faces by selecting two faces.

  • Refinement: for selected faces, new nodes are added in the middle of edges, and new faces are created

  • Split/merge faces: split quad face to two triangles if possible with the maximal created inner triangle-angles; merge two triangles, if possible, to a quad

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:

  • Support adding/move/remove vertices or faces while ensuring the consistency of the mesh.
  • Update the QgsTriangularMesh instance for every mesh editing without completely rebuild it. QgsTriangularMesh is used to render the mesh, and rebuilding it completely each time the mesh is edited would slow down the workflow and can't be acceptable with massive meshes.
  • Undo/redo editing action.

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:

  • faces of the native mesh that contains mesh vertices indexes,
  • Vertices indexes,
  • Triangular mesh that is used to display the mesh (see next chapter),

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:

  • Move vertices lead only to change the coordinates
  • Deleted vertices will be replaced with empty vertices
  • Deleted faces will be replace with empty faces
  • New vertices will be added at the end of the vertices container
  • New faces will be added at the end of the faces container

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:

  • Triangular mesh is defined in the map coordinates and native mesh in the layer coordinates
  • As there is one native mesh vertex for one triangular mesh vertex, relation between natives vertices and triangles vertices is bidirectional
  • Triangles of the triangular mesh are spatial indexed and can be retrieve by a point or an extent in the map
  • The relation between native faces and triangles are unidirectional with a map that relies triangles with associated native face

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 :

  • QgsMeshEditor class and the edit action
  • The interaction with the QgsTriangularMesh.

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
Copy link
Contributor

@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:

  • they need to use a left-click to start edit, left-click to finish (or right click to cancel) approach (as opposed to a click-hold-and-drag approach)
  • escape should also cancel the operation
  • the tools should derive from QgsMapToolAdvancedDigitizing, so that snapping works with the edits and CAD dock constraints are automatically respected

@troopa81
Copy link

troopa81 commented Jun 3, 2021

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

@michalkleczek
Copy link

michalkleczek commented Jun 5, 2021

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
Copy link

lucacarniato commented Jun 7, 2021

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
Copy link
Member Author

vcloarec commented Jun 7, 2021

@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
Copy link

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
Copy link
Member Author

vcloarec commented Mar 6, 2022

Hi @lucacarniato ,

Sorry for the delay...

I see two possible ways for mesh generation in QGIS:

  • Tool processing: creating a whole new mesh from some inputs (geometries, parameters,...), as TIN Mesh Creation already do, for a TIN DEM from vector layers. In a new processing tool, maybe it could also be possible to modify parts of existing mesh by adding or refining algorithms.

  • Mesh editing: add new parts or refine parts directly in an existing mesh in editing mode. A more direct way, more user friendly that allows undo/redo.

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
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants