Skip to content
Permalink
Browse files
[mesh] mesh frame editing part 3 - Edit mesh map tool (#44037)
[mesh] [feature] add mesh map tool to CRUD/digitize actions for mesh frame (vertices, faces)
  • Loading branch information
vcloarec committed Jul 14, 2021
1 parent 5762fe3 commit c09443a05695a971f9a721c1c223e3b14f4dedca
Showing with 4,801 additions and 397 deletions.
  1. +1 −0 images/images.qrc
  2. +1 −0 images/themes/default/mActionMeshDigitizing.svg
  3. +2 −1 python/core/auto_additions/qgis.py
  4. +9 −0 python/core/auto_generated/mesh/qgsmeshdataprovider.sip.in
  5. +63 −0 python/core/auto_generated/mesh/qgsmesheditor.sip.in
  6. +1 −0 python/core/auto_generated/qgis.sip.in
  7. +1 −1 src/3d/mesh/qgsmeshterraingenerator.cpp
  8. +1 −0 src/app/CMakeLists.txt
  9. +2 −0 src/app/maptools/qgsappmaptools.cpp
  10. +1 −0 src/app/maptools/qgsappmaptools.h
  11. +1,839 −0 src/app/mesh/qgsmaptooleditmeshframe.cpp
  12. +250 −0 src/app/mesh/qgsmaptooleditmeshframe.h
  13. +33 −16 src/app/qgisapp.cpp
  14. +8 −1 src/app/qgisapp.h
  15. +10 −0 src/core/mesh/qgsmeshdataprovider.h
  16. +3 −2 src/core/mesh/qgsmeshdataset.cpp
  17. +362 −41 src/core/mesh/qgsmesheditor.cpp
  18. +189 −2 src/core/mesh/qgsmesheditor.h
  19. +1 −1 src/core/mesh/qgsmeshlayer.cpp
  20. +5 −3 src/core/mesh/qgsmeshlayerrenderer.cpp
  21. +1 −0 src/core/mesh/qgsmeshlayerrenderer.h
  22. +795 −96 src/core/mesh/qgstopologicalmesh.cpp
  23. +135 −22 src/core/mesh/qgstopologicalmesh.h
  24. +112 −2 src/core/mesh/qgstriangularmesh.cpp
  25. +29 −9 src/core/mesh/qgstriangularmesh.h
  26. +1 −0 src/core/qgis.h
  27. +8 −0 src/providers/mdal/qgsmdalprovider.cpp
  28. +1 −0 src/providers/mdal/qgsmdalprovider.h
  29. +11 −0 src/ui/qgisapp.ui
  30. +1 −0 tests/src/app/CMakeLists.txt
  31. +288 −0 tests/src/app/testqgsmaptooleditmesh.cpp
  32. +15 −0 tests/src/app/testqgsmaptoolutils.h
  33. +616 −198 tests/src/core/testqgsmesheditor.cpp
  34. +6 −2 tests/testdata/mesh/quad_flower_to_edit_expected.2dm
@@ -921,6 +921,7 @@
<file>themes/default/mIconFolderLinkParams.svg</file>
<file>themes/default/mIconFolderHomeParams.svg</file>
<file>themes/default/mActionMeasureBearing.svg</file>
<file>themes/default/mActionMeshDigitizing.svg</file>
<file>themes/default/mActionNewMeshLayer.svg</file>
</qresource>
<qresource prefix="/images/tips">
@@ -0,0 +1 @@
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#5b6775" stroke-linecap="round" stroke-width="1.003672" transform="matrix(1.013697 0 0 .98287877 -.134578 .504371)"><path d="m13 2-11 11m0-11 11 11m-11.5-11.5h12v12h-12z"/><path d="m13.5 1.5h9v12h-9zm-12 12h12v9h-12zm20.5-11.5-8 11m-6.5 1v8"/><path d="m13 18h-11"/></g><g stroke-dashoffset=".5" stroke-linejoin="round" stroke-width="1.002" transform="matrix(1 0 0 .99552 31.548483 7.335066)"><path d="m-23.498 8.015 4.993 2.895-5.96 4.333z" fill="#505050" stroke="#2a2a2a" stroke-linecap="round" stroke-width=".752"/><path d="m-15.33-6.189 4.993 2.895-8.168 14.204-4.993-2.895z" fill="#fb7123" stroke="#474747" stroke-linecap="round" stroke-width=".752"/><path d="m-13.73-4.147-7.207 12.533" fill="none" opacity=".5" stroke="#fcffff" stroke-width="2.004"/><path d="m-12.066-3.183-7.207 12.534" fill-opacity=".706" opacity=".363" stroke="#000" stroke-width="2.004"/><g stroke-width=".501"><path d="m-23.195 13.985 4.038-3.168-1.662-.963-2.376 4.13z" fill="#969696" stroke="#969696" stroke-linecap="square"/><g fill="#e6e6e6"><path d="m-14.986-7.232 5.377 3.117-1.047 1.82-5.377-3.117z" stroke="#969696" stroke-linecap="round"/><path d="m-23.882 13.763.79-5.226 1.662.963z" stroke="#e6e6e6" stroke-linecap="square"/></g></g></g></svg>
@@ -402,10 +402,11 @@
# monkey patching scoped based enum
Qgis.MeshEditingErrorType.NoError.__doc__ = "No type"
Qgis.MeshEditingErrorType.InvalidFace.__doc__ = "An error occurs due to an invalid face (for example, vertex indexes are unordered)"
Qgis.MeshEditingErrorType.TooManyVerticesInFace.__doc__ = "A face has more vertices than the maximum number supported per face"
Qgis.MeshEditingErrorType.FlatFace.__doc__ = "A flat face is present"
Qgis.MeshEditingErrorType.UniqueSharedVertex.__doc__ = "A least two faces share only one vertices"
Qgis.MeshEditingErrorType.InvalidVertex.__doc__ = "An error occurs due to an invalid vertex (for example, vertex index is out of range the available vertex)"
Qgis.MeshEditingErrorType.__doc__ = 'Type of error that can occur during mesh frame editing.\n\n.. versionadded:: 3.22\n\n' + '* ``NoError``: ' + Qgis.MeshEditingErrorType.NoError.__doc__ + '\n' + '* ``InvalidFace``: ' + Qgis.MeshEditingErrorType.InvalidFace.__doc__ + '\n' + '* ``FlatFace``: ' + Qgis.MeshEditingErrorType.FlatFace.__doc__ + '\n' + '* ``UniqueSharedVertex``: ' + Qgis.MeshEditingErrorType.UniqueSharedVertex.__doc__ + '\n' + '* ``InvalidVertex``: ' + Qgis.MeshEditingErrorType.InvalidVertex.__doc__
Qgis.MeshEditingErrorType.__doc__ = 'Type of error that can occur during mesh frame editing.\n\n.. versionadded:: 3.22\n\n' + '* ``NoError``: ' + Qgis.MeshEditingErrorType.NoError.__doc__ + '\n' + '* ``InvalidFace``: ' + Qgis.MeshEditingErrorType.InvalidFace.__doc__ + '\n' + '* ``TooManyVerticesInFace``: ' + Qgis.MeshEditingErrorType.TooManyVerticesInFace.__doc__ + '\n' + '* ``FlatFace``: ' + Qgis.MeshEditingErrorType.FlatFace.__doc__ + '\n' + '* ``UniqueSharedVertex``: ' + Qgis.MeshEditingErrorType.UniqueSharedVertex.__doc__ + '\n' + '* ``InvalidVertex``: ' + Qgis.MeshEditingErrorType.InvalidVertex.__doc__
# --
Qgis.MeshEditingErrorType.baseClass = Qgis
# monkey patching scoped based enum
@@ -142,6 +142,15 @@ Returns number of edges in the native mesh
.. versionadded:: 3.14
%End

virtual int maximumVerticesCountPerFace() const;
%Docstring
Returns the maximum number of vertices per face supported by the current mesh,
if returns 0, the number of vertices is unlimited

:return: Maximum number of vertices per face

.. versionadded:: 3.22
%End
virtual void populateMesh( QgsMesh *mesh ) const = 0;
%Docstring
Populates the mesh vertices, edges and faces
@@ -63,6 +63,11 @@ Constructor with a specified layer ``meshLayer``
QgsMeshEditingError initialize();
%Docstring
Initialize the mesh editor and return errors if the internal native mesh have topologic errors
%End

bool faceCanBeAdded( const QgsMeshFace &face );
%Docstring
Returns ``True`` if a ``face`` can be added to the mesh
%End

QgsMeshEditingError addFace( const QVector<int> &vertexIndexes );
@@ -73,6 +78,37 @@ Adds a face ``face`` to the mesh with vertex indexes ``vertexIndexes``, returns
QgsMeshEditingError removeFaces( const QList<int> &facesToRemove );
%Docstring
Removes faces ``faces`` to the mesh, returns topological errors if this operation fails (operation is not realized)
%End

bool edgeCanBeFlipped( int vertexIndex1, int vertexIndex2 ) const;
%Docstring
Returns ``True`` if the edge can be flipped (only available for edge shared by two faces with 3 vertices)
%End

void flipEdge( int vertexIndex1, int vertexIndex2 );
%Docstring
Flips edge (``vertexIndex1``, ``vertexIndex2``)
%End

bool canBeMerged( int vertexIndex1, int vertexIndex2 ) const;
%Docstring
Returns ``True`` if faces separated by vertices with indexes ``vertexIndex1`` and ``vertexIndex2`` can be merged
%End

void merge( int vertexIndex1, int vertexIndex2 );
%Docstring
Merges faces separated by vertices with indexes ``vertexIndex1`` and ``vertexIndex2``
%End

bool faceCanBeSplit( int faceIndex ) const;
%Docstring
Returns ``True`` if face with index ``faceIndex`` can be split
%End

int splitFaces( const QList<int> &faceIndexes );
%Docstring
Splits faces with index ``faceIndexes``. Only faces that can be split are split.
Returns the count of faces effictively split
%End

int addPointsAsVertices( const QVector<QgsPoint> &point, double tolerance );
@@ -93,6 +129,17 @@ Removes vertices with indexes in the list ``verticesToRemoveIndexes`` in the mes
if ``fillHoles`` is set to ``True``, this operation will fill holes created in the mesh, if not remove the surrounding faces

If removing these vertices leads to a topological errors, the method will return the corresponding error and the operatio is canceled
%End

void changeZValues( const QList<int> &verticesIndexes, const QList<double> &newValues );
%Docstring
Changes the Z values of the vertices with indexes in ``vertices`` indexes with the values in ``newValues``
%End

void changeXYValues( const QList<int> &verticesIndexes, const QList<QgsPointXY> &newValues );
%Docstring
Changes the (X,Y) coordinates values of the vertices with indexes in ``vertices`` indexes with the values in ``newValues``.
The caller has the responsibility to check if changing the vertices coordinates does not lead to topological errors
%End

void stopEditing();
@@ -110,6 +157,22 @@ Returns the extent of the edited mesh
Returns whether the mesh has been modified
%End


QList<int> freeVerticesIndexes();
%Docstring
Returns all the free vertices indexes
%End

bool isVertexOnBoundary( int vertexIndex ) const;
%Docstring
Returns whether the vertex with index ``vertexIndex`` is on a boundary
%End

bool isVertexFree( int vertexIndex ) const;
%Docstring
Returns whether the vertex with index ``vertexIndex`` is a free vertex
%End

signals:
void meshEdited();
%Docstring
@@ -299,6 +299,7 @@ The development version
{
NoError,
InvalidFace,
TooManyVerticesInFace,
FlatFace,
UniqueSharedVertex,
InvalidVertex,
@@ -168,7 +168,7 @@ void QgsMeshTerrainGenerator::readXml( const QDomElement &elem )
float QgsMeshTerrainGenerator::heightAt( double x, double y, const Qgs3DMapSettings & ) const
{
QgsPointXY point( x, y );
int faceIndex = mTriangularMesh.faceIndexForPoint( point );
int faceIndex = mTriangularMesh.faceIndexForPoint_v2( point );
if ( faceIndex < 0 || faceIndex >= mTriangularMesh.triangles().count() )
return std::numeric_limits<float>::quiet_NaN();

@@ -246,6 +246,7 @@ set(QGIS_APP_SRCS

mesh/qgsmeshcalculatordialog.cpp
mesh/qgsnewmeshlayerdialog.cpp
mesh/qgsmaptooleditmeshframe.cpp
)

if (WITH_SPATIALITE)
@@ -69,6 +69,7 @@
#include "qgsmaptoolchangelabelproperties.h"
#include "qgsmaptoolpinlabels.h"
#include "qgsmaptooloffsetpointsymbol.h"
#include "qgsmaptooleditmeshframe.h"
#include "qgsspinbox.h"
#include "qgssettingsregistrycore.h"

@@ -176,6 +177,7 @@ QgsAppMapTools::QgsAppMapTools( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockW
mTools.insert( Tool::MoveLabel, new QgsMapToolMoveLabel( canvas, cadDock ) );
mTools.insert( Tool::RotateLabel, new QgsMapToolRotateLabel( canvas, cadDock ) );
mTools.insert( Tool::ChangeLabelProperties, new QgsMapToolChangeLabelProperties( canvas, cadDock ) );
mTools.insert( Tool::EditMeshFrame, new QgsMapToolEditMeshFrame( canvas ) );

mStreamDigitizingSettingsAction = new QgsStreamDigitizingSettingsAction();
}
@@ -113,6 +113,7 @@ class QgsAppMapTools
ChangeLabelProperties,
ReverseLine,
TrimExtendFeature,
EditMeshFrame
};

QgsAppMapTools( QgsMapCanvas *canvas, QgsAdvancedDigitizingDockWidget *cadDock );

0 comments on commit c09443a

Please sign in to comment.