QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsmesheditor.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmesheditor.cpp - QgsMeshEditor
3 
4  ---------------------
5  begin : 8.6.2021
6  copyright : (C) 2021 by Vincent Cloarec
7  email : vcloarec at gmail dot com
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include "qgis.h"
18 #include "qgsmesheditor.h"
19 #include "qgsmeshdataprovider.h"
20 #include "qgstriangularmesh.h"
21 #include "qgsmeshlayer.h"
22 #include "qgsmeshlayerutils.h"
23 #include "qgslogger.h"
24 #include "qgsgeometryengine.h"
25 #include "qgsmeshadvancedediting.h"
26 #include "qgsgeometryutils.h"
27 
28 #include <poly2tri.h>
29 
30 #include <QSet>
31 
32 
34  : QObject( meshLayer )
35  , mMesh( meshLayer ? meshLayer->nativeMesh() : nullptr )
36  , mTriangularMesh( meshLayer ? meshLayer->triangularMeshByLodIndex( 0 ) : nullptr )
37  , mUndoStack( meshLayer ? meshLayer->undoStack() : nullptr )
38 {
39  if ( meshLayer && meshLayer->dataProvider() )
40  mMaximumVerticesPerFace = meshLayer->dataProvider()->maximumVerticesCountPerFace();
41 
42  if ( meshLayer )
43  connect( mUndoStack, &QUndoStack::indexChanged, this, &QgsMeshEditor::meshEdited );
44 }
45 
46 QgsMeshEditor::QgsMeshEditor( QgsMesh *nativeMesh, QgsTriangularMesh *triangularMesh, QObject *parent )
47  : QObject( parent )
48  , mMesh( nativeMesh )
49  , mTriangularMesh( triangularMesh )
50 {
51  mUndoStack = new QUndoStack( this );
52  connect( mUndoStack, &QUndoStack::indexChanged, this, &QgsMeshEditor::meshEdited );
53 }
54 
56 {
57  std::unique_ptr<QgsMeshDatasetGroup> zValueDatasetGroup = std::make_unique<QgsMeshVerticesElevationDatasetGroup>( tr( "vertices Z value" ), mMesh );
58  mZValueDatasetGroup = zValueDatasetGroup.get();
59  return zValueDatasetGroup.release();
60 }
61 
63 
65 {
66  QgsMeshEditingError error;
67  mTopologicalMesh = QgsTopologicalMesh::createTopologicalMesh( mMesh, mMaximumVerticesPerFace, error );
68  mValidFacesCount = mMesh->faceCount();
69  mValidVerticesCount = mMesh->vertexCount();
70  return error;
71 }
72 
74 {
75  mTriangularMesh = triangularMesh;
76 }
77 
79 {
80  const QgsGeometry newFaceGeom = QgsMeshUtils::toGeometry( face, mTriangularMesh->vertices() );
81  std::unique_ptr<QgsGeometryEngine> geomEngine( QgsGeometry::createGeometryEngine( newFaceGeom.constGet() ) );
82  geomEngine->prepareGeometry();
83 
84  QgsRectangle boundingBox = newFaceGeom.boundingBox();
85  QList<int> newFaceVerticesIndexes( face.toList() );
86  int newFaceSize = face.count();
87  QList<int> concernedFaceIndex = mTriangularMesh->nativeFaceIndexForRectangle( boundingBox );
88  if ( !concernedFaceIndex.isEmpty() )
89  {
90  // for each concerned face, we take edges and, if no common vertex with the new face,
91  // check is the edge intersects or is contained in the new face
92  for ( const int faceIndex : concernedFaceIndex )
93  {
94  const QgsMeshFace &existingFace = mMesh->faces.at( faceIndex );
95  int existingFaceSize = existingFace.count();
96  bool shareVertex = false;
97  for ( int i = 0; i < existingFaceSize; ++i )
98  {
99  if ( newFaceVerticesIndexes.contains( existingFace.at( i ) ) )
100  {
101  shareVertex = true;
102  break;
103  }
104  }
105 
106  if ( shareVertex )
107  {
108  for ( int i = 0; i < existingFaceSize; ++i )
109  {
110  int index1 = existingFace.at( i );
111  int index2 = existingFace.at( ( i + 1 ) % existingFaceSize );
112  const QgsMeshVertex &v1 = mTriangularMesh->vertices().at( index1 );
113  const QgsMeshVertex &v2 = mTriangularMesh->vertices().at( index2 );
114  QgsGeometry edgeGeom = QgsGeometry( new QgsLineString( v1, v2 ) );
115 
116  if ( ! newFaceVerticesIndexes.contains( index1 ) && !newFaceVerticesIndexes.contains( index2 ) )
117  {
118  // test if the edge that not contains a shared vertex intersect the entire new face
119  if ( geomEngine->intersects( edgeGeom.constGet() ) )
120  return false;
121  }
122  else
123  {
124  for ( int vi = 0; vi < newFaceVerticesIndexes.count(); ++vi )
125  {
126  int vertInNewFace1 = newFaceVerticesIndexes.at( vi );
127  int vertInNewFace2 = newFaceVerticesIndexes.at( ( vi + 1 ) % newFaceSize );
128  if ( vertInNewFace1 != index1 && vertInNewFace2 != index2 && vertInNewFace1 != index2 && vertInNewFace2 != index1 )
129  {
130  const QgsMeshVertex &nv1 = mTriangularMesh->vertices().at( vertInNewFace1 );
131  const QgsMeshVertex &nv2 = mTriangularMesh->vertices().at( vertInNewFace2 );
132  QgsGeometry newEdgeGeom = QgsGeometry( new QgsLineString( nv1, nv2 ) );
133 
134  if ( newEdgeGeom.intersects( edgeGeom ) )
135  return false;
136  }
137  }
138  }
139  }
140  }
141  else
142  {
143  const QgsGeometry existingFaceGeom = QgsMeshUtils::toGeometry( existingFace, mTriangularMesh->vertices() );
144  if ( geomEngine->intersects( existingFaceGeom.constGet() ) )
145  return false;
146  }
147  }
148  }
149 
150  // Then search for free vertices included in the new face
151  const QList<int> &freeVertices = freeVerticesIndexes();
152 
153  for ( const int freeVertexIndex : freeVertices )
154  {
155  if ( newFaceVerticesIndexes.contains( freeVertexIndex ) )
156  continue;
157 
158  const QgsMeshVertex &vertex = mTriangularMesh->vertices().at( freeVertexIndex );
159  if ( geomEngine->contains( &vertex ) )
160  return false;
161  }
162 
163  return true;
164 }
165 
166 
168 {
169  QgsMeshEditingError error;
170 
171  // Prepare and check the face
172  QVector<QgsMeshFace> facesToAdd = prepareFaces( {face}, error );
173 
175  return false;
176 
177  // Check if there is topological error with the mesh
178  QgsTopologicalMesh::TopologicalFaces topologicalFaces = QgsTopologicalMesh::createNewTopologicalFaces( facesToAdd, true, error );
179  error = mTopologicalMesh.facesCanBeAdded( topologicalFaces );
180 
182  return false;
183 
184  // Check geometry compatibility
185  // With the topological check, we know that the new face is not included in an existing one
186  // But maybe, the new face includes or intersects existing faces or free vertices, we need to check
187  // First search for faces intersecting the bounding box of the new face.
188 
189  return isFaceGeometricallyCompatible( face );
190 }
191 
192 void QgsMeshEditor::applyEdit( QgsMeshEditor::Edit &edit )
193 {
194  mTopologicalMesh.applyChanges( edit.topologicalChanges );
195  mTriangularMesh->applyChanges( edit.triangularMeshChanges );
196 
197  if ( mZValueDatasetGroup &&
198  ( !edit.topologicalChanges.newVerticesZValues().isEmpty() ||
199  !edit.topologicalChanges.verticesToRemoveIndexes().isEmpty() ||
200  !edit.topologicalChanges.addedVertices().isEmpty() ) )
201  mZValueDatasetGroup->setStatisticObsolete();
202 
203  updateElementsCount( edit.topologicalChanges );
204 }
205 
206 void QgsMeshEditor::reverseEdit( QgsMeshEditor::Edit &edit )
207 {
208  mTopologicalMesh.reverseChanges( edit.topologicalChanges );
209  mTriangularMesh->reverseChanges( edit.triangularMeshChanges, *mMesh );
210 
211  if ( mZValueDatasetGroup &&
212  ( !edit.topologicalChanges.newVerticesZValues().isEmpty() ||
213  !edit.topologicalChanges.verticesToRemoveIndexes().isEmpty() ||
214  !edit.topologicalChanges.addedVertices().isEmpty() ) )
215  mZValueDatasetGroup->setStatisticObsolete();
216 
217  updateElementsCount( edit.topologicalChanges, false );
218 }
219 
220 void QgsMeshEditor::applyAddVertex( QgsMeshEditor::Edit &edit, const QgsMeshVertex &vertex, double tolerance )
221 {
222  QgsMeshVertex vertexInTriangularCoordinate = mTriangularMesh->nativeToTriangularCoordinates( vertex );
223 
224  //check if edges is closest than the tolerance from the vertex
225  int faceEdgeIntersect = -1;
226  int edgePosition = -1;
227 
228  QgsTopologicalMesh::Changes topologicChanges;
229 
230  if ( edgeIsClose( vertexInTriangularCoordinate, tolerance, faceEdgeIntersect, edgePosition ) )
231  {
232  topologicChanges = mTopologicalMesh.insertVertexInFacesEdge( faceEdgeIntersect, edgePosition, vertex );
233  }
234  else
235  {
236  int includingFaceIndex = mTriangularMesh->nativeFaceIndexForPoint( vertexInTriangularCoordinate );
237 
238  if ( includingFaceIndex != -1 )
239  topologicChanges = mTopologicalMesh.addVertexInFace( includingFaceIndex, vertex );
240  else
241  topologicChanges = mTopologicalMesh.addFreeVertex( vertex );
242  }
243 
244  applyEditOnTriangularMesh( edit, topologicChanges );
245 
246  if ( mZValueDatasetGroup )
247  mZValueDatasetGroup->setStatisticObsolete();
248 
249  updateElementsCount( edit.topologicalChanges );
250 }
251 
252 bool QgsMeshEditor::applyRemoveVertexFillHole( QgsMeshEditor::Edit &edit, int vertexIndex )
253 {
254  QgsTopologicalMesh::Changes changes = mTopologicalMesh.removeVertexFillHole( vertexIndex );
255 
256  if ( !changes.isEmpty() )
257  {
258  applyEditOnTriangularMesh( edit, changes );
259 
260  if ( mZValueDatasetGroup )
261  mZValueDatasetGroup->setStatisticObsolete();
262 
263  updateElementsCount( edit.topologicalChanges );
264  return true;
265  }
266  else
267  return false;
268 }
269 
270 void QgsMeshEditor::applyRemoveVerticesWithoutFillHole( QgsMeshEditor::Edit &edit, const QList<int> &verticesIndexes )
271 {
272  applyEditOnTriangularMesh( edit, mTopologicalMesh.removeVertices( verticesIndexes ) );
273 
274  if ( mZValueDatasetGroup )
275  mZValueDatasetGroup->setStatisticObsolete();
276 
277  updateElementsCount( edit.topologicalChanges );
278 }
279 
280 void QgsMeshEditor::applyAddFaces( QgsMeshEditor::Edit &edit, const QgsTopologicalMesh::TopologicalFaces &faces )
281 {
282  applyEditOnTriangularMesh( edit, mTopologicalMesh.addFaces( faces ) );
283 
284  updateElementsCount( edit.topologicalChanges );
285 }
286 
287 void QgsMeshEditor::applyRemoveFaces( QgsMeshEditor::Edit &edit, const QList<int> &faceToRemoveIndex )
288 {
289  applyEditOnTriangularMesh( edit, mTopologicalMesh.removeFaces( faceToRemoveIndex ) );
290 
291  updateElementsCount( edit.topologicalChanges );
292 }
293 
294 void QgsMeshEditor::applyChangeZValue( QgsMeshEditor::Edit &edit, const QList<int> &verticesIndexes, const QList<double> &newValues )
295 {
296  applyEditOnTriangularMesh( edit, mTopologicalMesh.changeZValue( verticesIndexes, newValues ) );
297 
298  if ( mZValueDatasetGroup )
299  mZValueDatasetGroup->setStatisticObsolete();
300 }
301 
302 void QgsMeshEditor::applyChangeXYValue( QgsMeshEditor::Edit &edit, const QList<int> &verticesIndexes, const QList<QgsPointXY> &newValues )
303 {
304  applyEditOnTriangularMesh( edit, mTopologicalMesh.changeXYValue( verticesIndexes, newValues ) );
305 }
306 
307 void QgsMeshEditor::applyFlipEdge( QgsMeshEditor::Edit &edit, int vertexIndex1, int vertexIndex2 )
308 {
309  applyEditOnTriangularMesh( edit, mTopologicalMesh.flipEdge( vertexIndex1, vertexIndex2 ) );
310 
311  updateElementsCount( edit.topologicalChanges );
312 }
313 
314 void QgsMeshEditor::applyMerge( QgsMeshEditor::Edit &edit, int vertexIndex1, int vertexIndex2 )
315 {
316  applyEditOnTriangularMesh( edit, mTopologicalMesh.merge( vertexIndex1, vertexIndex2 ) );
317 
318  updateElementsCount( edit.topologicalChanges );
319 }
320 
321 void QgsMeshEditor::applySplit( QgsMeshEditor::Edit &edit, int faceIndex )
322 {
323  applyEditOnTriangularMesh( edit, mTopologicalMesh.splitFace( faceIndex ) );
324 
325  updateElementsCount( edit.topologicalChanges );
326 }
327 
328 void QgsMeshEditor::applyAdvancedEdit( QgsMeshEditor::Edit &edit, QgsMeshAdvancedEditing *editing )
329 {
330  applyEditOnTriangularMesh( edit, editing->apply( this ) );
331 
332  updateElementsCount( edit.topologicalChanges );
333 
334  if ( mZValueDatasetGroup )
335  mZValueDatasetGroup->setStatisticObsolete();
336 }
337 
338 void QgsMeshEditor::applyEditOnTriangularMesh( QgsMeshEditor::Edit &edit, const QgsTopologicalMesh::Changes &topologicChanges )
339 {
340  QgsTriangularMesh::Changes triangularChanges( topologicChanges, *mMesh );
341  mTriangularMesh->applyChanges( triangularChanges );
342 
343  edit.topologicalChanges = topologicChanges;
344  edit.triangularMeshChanges = triangularChanges;
345 }
346 
347 void QgsMeshEditor::updateElementsCount( const QgsTopologicalMesh::Changes &changes, bool apply )
348 {
349  if ( apply )
350  {
351  mValidFacesCount += changes.addedFaces().count() - changes.removedFaces().count();
352  mValidVerticesCount += changes.addedVertices().count() - changes.verticesToRemoveIndexes().count();
353  }
354  else
355  {
356  //reverse
357  mValidFacesCount -= changes.addedFaces().count() - changes.removedFaces().count();
358  mValidVerticesCount -= changes.addedVertices().count() - changes.verticesToRemoveIndexes().count();
359  }
360 }
361 
363 {
364  error = mTopologicalMesh.checkConsistency();
365  switch ( error.errorType )
366  {
368  break;
375  return false;
376  }
377 
378  if ( mTriangularMesh->vertices().count() != mMesh->vertexCount() )
379  return false;
380 
381  if ( mTriangularMesh->faceCentroids().count() != mMesh->faceCount() )
382  return false;
383 
384  return true;
385 }
386 
387 bool QgsMeshEditor::edgeIsClose( QgsPointXY point, double tolerance, int &faceIndex, int &edgePosition )
388 {
389  QgsRectangle toleranceZone( point.x() - tolerance,
390  point.y() - tolerance,
391  point.x() + tolerance,
392  point.y() + tolerance );
393 
394  edgePosition = -1;
395  double minDist = std::numeric_limits<double>::max();
396  const QList<int> &nativeFaces = mTriangularMesh->nativeFaceIndexForRectangle( toleranceZone );
397  double epsilon = std::numeric_limits<double>::epsilon() * tolerance;
398  for ( const int nativeFaceIndex : nativeFaces )
399  {
400  const QgsMeshFace &face = mMesh->face( nativeFaceIndex );
401  const int faceSize = face.size();
402  for ( int i = 0; i < faceSize; ++i )
403  {
404  const QgsMeshVertex &v1 = mTriangularMesh->vertices().at( face.at( i ) );
405  const QgsMeshVertex &v2 = mTriangularMesh->vertices().at( face.at( ( i + 1 ) % faceSize ) );
406 
407  double mx, my;
408  double dist = sqrt( QgsGeometryUtils::sqrDistToLine( point.x(),
409  point.y(),
410  v1.x(),
411  v1.y(),
412  v2.x(),
413  v2.y(),
414  mx,
415  my,
416  epsilon ) );
417 
418  if ( dist < tolerance && dist < minDist )
419  {
420  faceIndex = nativeFaceIndex;
421  edgePosition = i;
422  minDist = dist;
423  }
424  }
425  }
426 
427  if ( edgePosition != -1 )
428  return true;
429 
430  return false;
431 
432 }
433 
435 {
436  return mValidFacesCount;
437 }
438 
440 {
441  return mValidVerticesCount;
442 }
443 
445 {
446  return mMaximumVerticesPerFace;
447 }
448 
449 QgsMeshEditingError QgsMeshEditor::removeFaces( const QList<int> &facesToRemove )
450 {
451  QgsMeshEditingError error = mTopologicalMesh.facesCanBeRemoved( facesToRemove );
453  return error;
454 
455  mUndoStack->push( new QgsMeshLayerUndoCommandRemoveFaces( this, facesToRemove ) );
456 
457  return error;
458 }
459 
460 bool QgsMeshEditor::edgeCanBeFlipped( int vertexIndex1, int vertexIndex2 ) const
461 {
462  return mTopologicalMesh.edgeCanBeFlipped( vertexIndex1, vertexIndex2 );
463 }
464 
465 void QgsMeshEditor::flipEdge( int vertexIndex1, int vertexIndex2 )
466 {
467  if ( !edgeCanBeFlipped( vertexIndex1, vertexIndex2 ) )
468  return;
469 
470  mUndoStack->push( new QgsMeshLayerUndoCommandFlipEdge( this, vertexIndex1, vertexIndex2 ) );
471 }
472 
473 bool QgsMeshEditor::canBeMerged( int vertexIndex1, int vertexIndex2 ) const
474 {
475  return mTopologicalMesh.canBeMerged( vertexIndex1, vertexIndex2 );
476 }
477 
478 void QgsMeshEditor::merge( int vertexIndex1, int vertexIndex2 )
479 {
480  if ( !canBeMerged( vertexIndex1, vertexIndex2 ) )
481  return;
482 
483  mUndoStack->push( new QgsMeshLayerUndoCommandMerge( this, vertexIndex1, vertexIndex2 ) );
484 }
485 
486 bool QgsMeshEditor::faceCanBeSplit( int faceIndex ) const
487 {
488  return mTopologicalMesh.canBeSplit( faceIndex );
489 }
490 
491 int QgsMeshEditor::splitFaces( const QList<int> &faceIndexes )
492 {
493  QList<int> faceIndexesSplittable;
494 
495  for ( const int faceIndex : faceIndexes )
496  if ( faceCanBeSplit( faceIndex ) )
497  faceIndexesSplittable.append( faceIndex );
498 
499  if ( faceIndexesSplittable.isEmpty() )
500  return 0;
501 
502  mUndoStack->push( new QgsMeshLayerUndoCommandSplitFaces( this, faceIndexesSplittable ) );
503 
504  return faceIndexesSplittable.count();
505 }
506 
507 QVector<QgsMeshFace> QgsMeshEditor::prepareFaces( const QVector<QgsMeshFace> &faces, QgsMeshEditingError &error )
508 {
509  QVector<QgsMeshFace> treatedFaces = faces;
510 
511  // here we could add later some filters, for example, removing faces intersecting with existing one
512 
513  for ( int i = 0; i < treatedFaces.count(); ++i )
514  {
515  QgsMeshFace &face = treatedFaces[i];
516  if ( mMaximumVerticesPerFace != 0 && face.count() > mMaximumVerticesPerFace )
517  {
519  break;
520  }
521 
522  error = QgsTopologicalMesh::counterClockwiseFaces( face, mMesh );
524  break;
525  }
526 
527  return treatedFaces;
528 }
529 
530 QgsMeshEditingError QgsMeshEditor::addFaces( const QVector<QVector<int> > &faces )
531 {
532  QgsMeshEditingError error;
533  QVector<QgsMeshFace> facesToAdd = prepareFaces( faces, error );
534 
536  return error;
537 
538  QgsTopologicalMesh::TopologicalFaces topologicalFaces = QgsTopologicalMesh::createNewTopologicalFaces( facesToAdd, true, error );
539 
540  error = mTopologicalMesh.facesCanBeAdded( topologicalFaces );
541 
543  return error;
544 
545  mUndoStack->push( new QgsMeshLayerUndoCommandAddFaces( this, topologicalFaces ) );
546 
547  return error;
548 }
549 
550 QgsMeshEditingError QgsMeshEditor::addFace( const QVector<int> &vertexIndexes )
551 {
552  return addFaces( {vertexIndexes} );
553 }
554 
555 int QgsMeshEditor::addVertices( const QVector<QgsMeshVertex> &vertices, double tolerance )
556 {
557  QVector<QgsMeshVertex> verticesInLayerCoordinate( vertices.count() );
558  int ignoredVertex = 0;
559  for ( int i = 0; i < vertices.count(); ++i )
560  {
561  const QgsPointXY &pointInTriangularMesh = vertices.at( i );
562  bool isTooClose = false;
563  int triangleIndex = mTriangularMesh->faceIndexForPoint_v2( pointInTriangularMesh );
564  if ( triangleIndex != -1 )
565  {
566  const QgsMeshFace face = mTriangularMesh->triangles().at( triangleIndex );
567  for ( int j = 0; j < 3; ++j )
568  {
569  const QgsPointXY &facePoint = mTriangularMesh->vertices().at( face.at( j ) );
570  double dist = pointInTriangularMesh.distance( facePoint );
571  if ( dist < tolerance )
572  {
573  isTooClose = true;
574  break;
575  }
576  }
577  }
578 
579  if ( !isTooClose )
580  verticesInLayerCoordinate[i] = mTriangularMesh->triangularToNativeCoordinates( vertices.at( i ) );
581  else
582  verticesInLayerCoordinate[i] = QgsMeshVertex();
583 
584  if ( verticesInLayerCoordinate.at( i ).isEmpty() )
585  ignoredVertex++;
586  }
587 
588  if ( ignoredVertex < vertices.count() )
589  {
590  mUndoStack->push( new QgsMeshLayerUndoCommandAddVertices( this, verticesInLayerCoordinate, tolerance ) );
591  }
592 
593  int effectivlyAddedVertex = vertices.count() - ignoredVertex;
594 
595  return effectivlyAddedVertex;
596 }
597 
598 int QgsMeshEditor::addPointsAsVertices( const QVector<QgsPoint> &point, double tolerance )
599 {
600  return addVertices( point, tolerance );
601 }
602 
603 QgsMeshEditingError QgsMeshEditor::removeVerticesWithoutFillHoles( const QList<int> &verticesToRemoveIndexes )
604 {
605  QgsMeshEditingError error;
606 
607  QList<int> verticesIndexes = verticesToRemoveIndexes;
608 
609  QSet<int> concernedNativeFaces;
610  for ( const int vi : std::as_const( verticesIndexes ) )
611  concernedNativeFaces.unite( qgis::listToSet( mTopologicalMesh.facesAroundVertex( vi ) ) );
612 
613  error = mTopologicalMesh.facesCanBeRemoved( concernedNativeFaces.values() );
614 
616  return error;
617 
618  mUndoStack->push( new QgsMeshLayerUndoCommandRemoveVerticesWithoutFillHoles( this, verticesIndexes ) );
619  return error;
620 }
621 
622 QList<int> QgsMeshEditor::removeVerticesFillHoles( const QList<int> &verticesToRemoveIndexes )
623 {
624  QList<int> remainingVertices;
625  mUndoStack->push( new QgsMeshLayerUndoCommandRemoveVerticesFillHoles( this, verticesToRemoveIndexes, &remainingVertices ) );
626 
627  return remainingVertices;
628 }
629 
630 
631 void QgsMeshEditor::changeZValues( const QList<int> &verticesIndexes, const QList<double> &newZValues )
632 {
633  mUndoStack->push( new QgsMeshLayerUndoCommandChangeZValue( this, verticesIndexes, newZValues ) );
634 }
635 
636 bool QgsMeshEditor::canBeTransformed( const QList<int> &facesToCheck, const std::function<const QgsMeshVertex( int )> &transformFunction ) const
637 {
638  for ( const int faceIndex : facesToCheck )
639  {
640  const QgsMeshFace &face = mMesh->face( faceIndex );
641  int faceSize = face.count();
642  QVector<QgsPointXY> pointsInTriangularMeshCoordinate( faceSize );
643  QVector<QgsPointXY> points( faceSize );
644  for ( int i = 0; i < faceSize; ++i )
645  {
646  int ip0 = face[i];
647  int ip1 = face[( i + 1 ) % faceSize];
648  int ip2 = face[( i + 2 ) % faceSize];
649 
650  QgsMeshVertex p0 = transformFunction( ip0 );
651  QgsMeshVertex p1 = transformFunction( ip1 );
652  QgsMeshVertex p2 = transformFunction( ip2 );
653 
654  double ux = p0.x() - p1.x();
655  double uy = p0.y() - p1.y();
656  double vx = p2.x() - p1.x();
657  double vy = p2.y() - p1.y();
658 
659  double crossProduct = ux * vy - uy * vx;
660  if ( crossProduct >= 0 ) //if cross product>0, we have two edges clockwise
661  return false;
662  pointsInTriangularMeshCoordinate[i] = mTriangularMesh->nativeToTriangularCoordinates( p0 );
663  points[i] = p0;
664  }
665 
666  const QgsGeometry &deformedFace = QgsGeometry::fromPolygonXY( {points} );
667 
668  // now test if the deformed face contain something else
669  QList<int> otherFaceIndexes =
670  mTriangularMesh->nativeFaceIndexForRectangle( QgsGeometry::fromPolygonXY( {pointsInTriangularMeshCoordinate} ).boundingBox() );
671 
672  for ( const int otherFaceIndex : otherFaceIndexes )
673  {
674  const QgsMeshFace &otherFace = mMesh->face( otherFaceIndex );
675  int existingFaceSize = otherFace.count();
676  bool shareVertex = false;
677  for ( int i = 0; i < existingFaceSize; ++i )
678  {
679  if ( face.contains( otherFace.at( i ) ) )
680  {
681  shareVertex = true;
682  break;
683  }
684  }
685  if ( shareVertex )
686  {
687  //only test the edge that not contains a shared vertex
688  for ( int i = 0; i < existingFaceSize; ++i )
689  {
690  int index1 = otherFace.at( i );
691  int index2 = otherFace.at( ( i + 1 ) % existingFaceSize );
692  if ( ! face.contains( index1 ) && !face.contains( index2 ) )
693  {
694  const QgsPointXY &v1 = transformFunction( index1 );
695  const QgsPointXY &v2 = transformFunction( index2 );
696  QgsGeometry edgeGeom = QgsGeometry::fromPolylineXY( { v1, v2} );
697  if ( deformedFace.intersects( edgeGeom ) )
698  return false;
699  }
700  }
701  }
702  else
703  {
704  QVector<QgsPointXY> otherPoints( existingFaceSize );
705  for ( int i = 0; i < existingFaceSize; ++i )
706  otherPoints[i] = transformFunction( otherFace.at( i ) );
707  const QgsGeometry existingFaceGeom = QgsGeometry::fromPolygonXY( {otherPoints } );
708  if ( deformedFace.intersects( existingFaceGeom ) )
709  return false;
710  }
711  }
712 
713  const QList<int> freeVerticesIndex = freeVerticesIndexes();
714  for ( const int vertexIndex : freeVerticesIndex )
715  {
716  const QgsPointXY &mapPoint = transformFunction( vertexIndex ); //free vertices can be transformed
717  if ( deformedFace.contains( &mapPoint ) )
718  return false;
719  }
720  }
721 
722  // free vertices
723  const QList<int> freeVerticesIndex = freeVerticesIndexes();
724  for ( const int vertexIndex : freeVerticesIndex )
725  {
726  const QgsMeshVertex &newFreeVertexPosition = transformFunction( vertexIndex ); // transformed free vertex
727  const QgsMeshVertex pointInTriangularCoord = mTriangularMesh->nativeToTriangularCoordinates( newFreeVertexPosition );
728  const int originalIncludingFace = mTriangularMesh->nativeFaceIndexForPoint( pointInTriangularCoord );
729 
730  if ( originalIncludingFace != -1 )
731  {
732  // That means two things: the free vertex is moved AND is included in a face before transform
733  // Before returning false, we need to check if the vertex is still in the face after transform
734  const QgsMeshFace &face = mMesh->face( originalIncludingFace );
735  int faceSize = face.count();
736  QVector<QgsPointXY> points( faceSize );
737  for ( int i = 0; i < faceSize; ++i )
738  points[i] = transformFunction( face.at( i ) );
739 
740  const QgsGeometry &deformedFace = QgsGeometry::fromPolygonXY( {points} );
741  const QgsPointXY ptXY( newFreeVertexPosition );
742  if ( deformedFace.contains( &ptXY ) )
743  return false;
744  }
745  }
746 
747  return true;
748 }
749 
750 void QgsMeshEditor::changeXYValues( const QList<int> &verticesIndexes, const QList<QgsPointXY> &newValues )
751 {
752  // TODO : implement a check if it is possible to change the (x,y) values. For now, this check is made in the APP part
753  mUndoStack->push( new QgsMeshLayerUndoCommandChangeXYValue( this, verticesIndexes, newValues ) );
754 }
755 
756 void QgsMeshEditor::changeCoordinates( const QList<int> &verticesIndexes, const QList<QgsPoint> &newCoordinates )
757 {
758  mUndoStack->push( new QgsMeshLayerUndoCommandChangeCoordinates( this, verticesIndexes, newCoordinates ) );
759 }
760 
762 {
763  mUndoStack->push( new QgsMeshLayerUndoCommandAdvancedEditing( this, editing ) );
764 }
765 
767 {
768  mTopologicalMesh.reindex();
769  mUndoStack->clear();
770 }
771 
773  : mMeshEditor( meshEditor )
774 {
775 }
776 
778 {
779  if ( mMeshEditor.isNull() )
780  return;
781 
782  for ( int i = mEdits.count() - 1; i >= 0; --i )
783  mMeshEditor->reverseEdit( mEdits[i] );
784 }
785 
787 {
788  if ( mMeshEditor.isNull() )
789  return;
790 
791  for ( QgsMeshEditor::Edit &edit : mEdits )
792  mMeshEditor->applyEdit( edit );
793 }
794 
795 QgsMeshLayerUndoCommandAddVertices::QgsMeshLayerUndoCommandAddVertices( QgsMeshEditor *meshEditor, const QVector<QgsMeshVertex> &vertices, double tolerance )
796  : QgsMeshLayerUndoCommandMeshEdit( meshEditor )
797  , mVertices( vertices )
798  , mTolerance( tolerance )
799 {
800  setText( QObject::tr( "Add %n vertices", nullptr, mVertices.count() ) );
801 }
802 
804 {
805  if ( !mVertices.isEmpty() )
806  {
807  for ( int i = 0; i < mVertices.count(); ++i )
808  {
809  const QgsMeshVertex &vertex = mVertices.at( i );
810  if ( vertex.isEmpty() )
811  continue;
812  QgsMeshEditor::Edit edit;
813  mMeshEditor->applyAddVertex( edit, vertex, mTolerance );
814  mEdits.append( edit );
815  }
816  mVertices.clear(); //not needed anymore, changes are store in mEdits
817  }
818  else
819  {
820  for ( QgsMeshEditor::Edit &edit : mEdits )
821  mMeshEditor->applyEdit( edit );
822  }
823 }
824 
826  QgsMeshEditor *meshEditor,
827  const QList<int> &verticesToRemoveIndexes,
828  QList<int> *remainingVerticesPointer )
829  : QgsMeshLayerUndoCommandMeshEdit( meshEditor )
830  , mVerticesToRemoveIndexes( verticesToRemoveIndexes )
831  , mRemainingVerticesPointer( remainingVerticesPointer )
832 {
833  setText( QObject::tr( "Remove %n vertices filling holes", nullptr, verticesToRemoveIndexes.count() ) );
834 }
835 
837 {
838  int initialVertexCount = mVerticesToRemoveIndexes.count();
839  if ( !mVerticesToRemoveIndexes.isEmpty() )
840  {
841  QgsMeshEditor::Edit edit;
842  QList<int> vertexToRetry;
843  while ( !mVerticesToRemoveIndexes.isEmpty() )
844  {
845  // try again and again until there is no vertices to remove anymore or nothing is removed.
846  for ( const int &vertex : std::as_const( mVerticesToRemoveIndexes ) )
847  {
848  if ( mMeshEditor->applyRemoveVertexFillHole( edit, vertex ) )
849  mEdits.append( edit );
850  else
851  vertexToRetry.append( vertex );
852  }
853 
854  if ( vertexToRetry.count() == mVerticesToRemoveIndexes.count() )
855  break;
856  else
857  mVerticesToRemoveIndexes = vertexToRetry;
858  }
859 
860  if ( initialVertexCount == mVerticesToRemoveIndexes.count() )
861  setObsolete( true );
862 
863  if ( mRemainingVerticesPointer != nullptr )
864  *mRemainingVerticesPointer = mVerticesToRemoveIndexes;
865 
866  mRemainingVerticesPointer = nullptr;
867 
868  mVerticesToRemoveIndexes.clear(); //not needed anymore, changes are store in mEdits
869  }
870  else
871  {
872  for ( QgsMeshEditor::Edit &edit : mEdits )
873  mMeshEditor->applyEdit( edit );
874  }
875 }
876 
877 
879  QgsMeshEditor *meshEditor,
880  const QList<int> &verticesToRemoveIndexes )
881  : QgsMeshLayerUndoCommandMeshEdit( meshEditor )
882  , mVerticesToRemoveIndexes( verticesToRemoveIndexes )
883 {
884  setText( QObject::tr( "Remove %n vertices without filling holes", nullptr, verticesToRemoveIndexes.count() ) ) ;
885 }
886 
888 {
889  if ( !mVerticesToRemoveIndexes.isEmpty() )
890  {
891  QgsMeshEditor::Edit edit;
892 
893  mMeshEditor->applyRemoveVerticesWithoutFillHole( edit, mVerticesToRemoveIndexes );
894  mEdits.append( edit );
895 
896  mVerticesToRemoveIndexes.clear(); //not needed anymore, changes are store in mEdits
897  }
898  else
899  {
900  for ( QgsMeshEditor::Edit &edit : mEdits )
901  mMeshEditor->applyEdit( edit );
902  }
903 }
904 
906  : QgsMeshLayerUndoCommandMeshEdit( meshEditor )
907  , mFaces( faces )
908 {
909  setText( QObject::tr( "Add %n face(s)", nullptr, faces.meshFaces().count() ) );
910 }
911 
913 {
914  if ( !mFaces.meshFaces().isEmpty() )
915  {
916  QgsMeshEditor::Edit edit;
917  mMeshEditor->applyAddFaces( edit, mFaces );
918  mEdits.append( edit );
919 
920  mFaces.clear(); //not needed anymore, now changes are store in edit
921  }
922  else
923  {
924  for ( QgsMeshEditor::Edit &edit : mEdits )
925  mMeshEditor->applyEdit( edit );
926  }
927 }
928 
929 QgsMeshLayerUndoCommandRemoveFaces::QgsMeshLayerUndoCommandRemoveFaces( QgsMeshEditor *meshEditor, const QList<int> &facesToRemoveIndexes )
930  : QgsMeshLayerUndoCommandMeshEdit( meshEditor )
931  , mfacesToRemoveIndexes( facesToRemoveIndexes )
932 {
933  setText( QObject::tr( "Remove %n face(s)", nullptr, facesToRemoveIndexes.count() ) );
934 }
935 
937 {
938  if ( !mfacesToRemoveIndexes.isEmpty() )
939  {
940  QgsMeshEditor::Edit edit;
941  mMeshEditor->applyRemoveFaces( edit, mfacesToRemoveIndexes );
942  mEdits.append( edit );
943 
944  mfacesToRemoveIndexes.clear(); //not needed anymore, now changes are store in edit
945  }
946  else
947  {
948  for ( QgsMeshEditor::Edit &edit : mEdits )
949  mMeshEditor->applyEdit( edit );
950  }
951 }
952 
953 QgsMeshEditingError::QgsMeshEditingError(): errorType( Qgis::MeshEditingErrorType::NoError ), elementIndex( -1 ) {}
954 
955 QgsMeshEditingError::QgsMeshEditingError( Qgis::MeshEditingErrorType type, int elementIndex ): errorType( type ), elementIndex( elementIndex ) {}
956 
958 {
959  return mTriangularMesh->nativeExtent();
960 }
961 
963 {
964  if ( mUndoStack )
965  return !mUndoStack->isClean();
966 
967  return false;
968 }
969 
970 bool QgsMeshEditor::reindex( bool renumbering )
971 {
972  mTopologicalMesh.reindex();
973  mUndoStack->clear();
975  mValidFacesCount = mMesh->faceCount();
976  mValidVerticesCount = mMesh->vertexCount();
977 
979  return false;
980 
981  if ( renumbering )
982  {
983  if ( !mTopologicalMesh.renumber() )
984  return false;
985 
988  }
989 
990  else
991  return true;
992 }
993 
995 {
996  return mTopologicalMesh.freeVerticesIndexes();
997 }
998 
999 bool QgsMeshEditor::isVertexOnBoundary( int vertexIndex ) const
1000 {
1001  return mTopologicalMesh.isVertexOnBoundary( vertexIndex );
1002 }
1003 
1004 bool QgsMeshEditor::isVertexFree( int vertexIndex ) const
1005 {
1006  return mTopologicalMesh.isVertexFree( vertexIndex );
1007 }
1008 
1010 {
1011  return mTopologicalMesh.vertexCirculator( vertexIndex );
1012 }
1013 
1015 {
1016  return mTopologicalMesh;
1017 }
1018 
1020 {
1021  return mTriangularMesh;
1022 }
1023 
1024 QgsMeshLayerUndoCommandChangeZValue::QgsMeshLayerUndoCommandChangeZValue( QgsMeshEditor *meshEditor, const QList<int> &verticesIndexes, const QList<double> &newValues )
1025  : QgsMeshLayerUndoCommandMeshEdit( meshEditor )
1026  , mVerticesIndexes( verticesIndexes )
1027  , mNewValues( newValues )
1028 {
1029  setText( QObject::tr( "Change %n vertices Z Value", nullptr, verticesIndexes.count() ) );
1030 }
1031 
1033 {
1034  if ( !mVerticesIndexes.isEmpty() )
1035  {
1036  QgsMeshEditor::Edit edit;
1037  mMeshEditor->applyChangeZValue( edit, mVerticesIndexes, mNewValues );
1038  mEdits.append( edit );
1039  mVerticesIndexes.clear();
1040  mNewValues.clear();
1041  }
1042  else
1043  {
1044  for ( QgsMeshEditor::Edit &edit : mEdits )
1045  mMeshEditor->applyEdit( edit );
1046  }
1047 }
1048 
1049 QgsMeshLayerUndoCommandChangeXYValue::QgsMeshLayerUndoCommandChangeXYValue( QgsMeshEditor *meshEditor, const QList<int> &verticesIndexes, const QList<QgsPointXY> &newValues )
1050  : QgsMeshLayerUndoCommandMeshEdit( meshEditor )
1051  , mVerticesIndexes( verticesIndexes )
1052  , mNewValues( newValues )
1053 {
1054  setText( QObject::tr( "Move %n vertices", nullptr, verticesIndexes.count() ) );
1055 }
1056 
1058 {
1059  if ( !mVerticesIndexes.isEmpty() )
1060  {
1061  QgsMeshEditor::Edit edit;
1062  mMeshEditor->applyChangeXYValue( edit, mVerticesIndexes, mNewValues );
1063  mEdits.append( edit );
1064  mVerticesIndexes.clear();
1065  mNewValues.clear();
1066  }
1067  else
1068  {
1069  for ( QgsMeshEditor::Edit &edit : mEdits )
1070  mMeshEditor->applyEdit( edit );
1071  }
1072 }
1073 
1074 
1075 QgsMeshLayerUndoCommandChangeCoordinates::QgsMeshLayerUndoCommandChangeCoordinates( QgsMeshEditor *meshEditor, const QList<int> &verticesIndexes, const QList<QgsPoint> &newCoordinates )
1076  : QgsMeshLayerUndoCommandMeshEdit( meshEditor )
1077  , mVerticesIndexes( verticesIndexes )
1078  , mNewCoordinates( newCoordinates )
1079 {
1080  setText( QObject::tr( "Transform %n vertices coordinates", nullptr, verticesIndexes.count() ) );
1081 }
1082 
1084 {
1085  if ( !mVerticesIndexes.isEmpty() )
1086  {
1087  QgsMeshEditor::Edit editXY;
1088  QList<QgsPointXY> newXY;
1089  newXY.reserve( mNewCoordinates.count() );
1090  QgsMeshEditor::Edit editZ;
1091  QList<double> newZ;
1092  newZ.reserve( mNewCoordinates.count() );
1093 
1094  for ( const QgsPoint &pt : std::as_const( mNewCoordinates ) )
1095  {
1096  newXY.append( pt );
1097  newZ.append( pt.z() );
1098  }
1099 
1100  mMeshEditor->applyChangeXYValue( editXY, mVerticesIndexes, newXY );
1101  mEdits.append( editXY );
1102  mMeshEditor->applyChangeZValue( editZ, mVerticesIndexes, newZ );
1103  mEdits.append( editZ );
1104  mVerticesIndexes.clear();
1105  mNewCoordinates.clear();
1106  }
1107  else
1108  {
1109  for ( QgsMeshEditor::Edit &edit : mEdits )
1110  mMeshEditor->applyEdit( edit );
1111  }
1112 }
1113 
1114 
1115 
1117  : QgsMeshLayerUndoCommandMeshEdit( meshEditor )
1118  , mVertexIndex1( vertexIndex1 )
1119  , mVertexIndex2( vertexIndex2 )
1120 {
1121  setText( QObject::tr( "Flip edge" ) );
1122 }
1123 
1125 {
1126  if ( mVertexIndex1 >= 0 && mVertexIndex2 >= 0 )
1127  {
1128  QgsMeshEditor::Edit edit;
1129  mMeshEditor->applyFlipEdge( edit, mVertexIndex1, mVertexIndex2 );
1130  mEdits.append( edit );
1131  mVertexIndex1 = -1;
1132  mVertexIndex2 = -1;
1133  }
1134  else
1135  {
1136  for ( QgsMeshEditor::Edit &edit : mEdits )
1137  mMeshEditor->applyEdit( edit );
1138  }
1139 }
1140 
1141 QgsMeshLayerUndoCommandMerge::QgsMeshLayerUndoCommandMerge( QgsMeshEditor *meshEditor, int vertexIndex1, int vertexIndex2 )
1142  : QgsMeshLayerUndoCommandMeshEdit( meshEditor )
1143  , mVertexIndex1( vertexIndex1 )
1144  , mVertexIndex2( vertexIndex2 )
1145 {
1146  setText( QObject::tr( "Merge faces" ) );
1147 }
1148 
1150 {
1151  if ( mVertexIndex1 >= 0 && mVertexIndex2 >= 0 )
1152  {
1153  QgsMeshEditor::Edit edit;
1154  mMeshEditor->applyMerge( edit, mVertexIndex1, mVertexIndex2 );
1155  mEdits.append( edit );
1156  mVertexIndex1 = -1;
1157  mVertexIndex2 = -1;
1158  }
1159  else
1160  {
1161  for ( QgsMeshEditor::Edit &edit : mEdits )
1162  mMeshEditor->applyEdit( edit );
1163  }
1164 }
1165 
1167  : QgsMeshLayerUndoCommandMeshEdit( meshEditor )
1168  , mFaceIndexes( faceIndexes )
1169 {
1170  setText( QObject::tr( "Split %n face(s)", nullptr, faceIndexes.count() ) );
1171 }
1172 
1174 {
1175  if ( !mFaceIndexes.isEmpty() )
1176  {
1177  for ( int faceIndex : std::as_const( mFaceIndexes ) )
1178  {
1179  QgsMeshEditor::Edit edit;
1180  mMeshEditor->applySplit( edit, faceIndex );
1181  mEdits.append( edit );
1182  }
1183  mFaceIndexes.clear();
1184  }
1185  else
1186  {
1187  for ( QgsMeshEditor::Edit &edit : mEdits )
1188  mMeshEditor->applyEdit( edit );
1189  }
1190 }
1191 
1193  : QgsMeshLayerUndoCommandMeshEdit( meshEditor )
1194  , mAdvancedEditing( advancdEdit )
1195 {
1196  setText( advancdEdit->text() );
1197 }
1198 
1200 {
1201  if ( mAdvancedEditing )
1202  {
1203  QgsMeshEditor::Edit edit;
1204  while ( !mAdvancedEditing->isFinished() )
1205  {
1206  mMeshEditor->applyAdvancedEdit( edit, mAdvancedEditing );
1207  mEdits.append( edit );
1208  }
1209 
1210  mAdvancedEditing = nullptr;
1211  }
1212  else
1213  {
1214  for ( QgsMeshEditor::Edit &edit : mEdits )
1215  mMeshEditor->applyEdit( edit );
1216  }
1217 }
qgsmeshlayerutils.h
QgsMeshAdvancedEditing
Abstract class that can be derived to implement advanced editing on mesh.
Definition: qgsmeshadvancedediting.h:38
QgsTopologicalMesh::isVertexFree
bool isVertexFree(int vertexIndex) const
Returns whether the vertex is a free vertex.
Definition: qgstopologicalmesh.cpp:614
QgsPointXY::distance
double distance(double x, double y) const SIP_HOLDGIL
Returns the distance between this point and a specified x, y coordinate.
Definition: qgspointxy.h:211
QgsTopologicalMesh::Changes::addedVertices
QVector< QgsMeshVertex > addedVertices() const
Returns the added vertices with this changes.
Definition: qgstopologicalmesh.cpp:1014
QgsMeshLayerUndoCommandFlipEdge::QgsMeshLayerUndoCommandFlipEdge
QgsMeshLayerUndoCommandFlipEdge(QgsMeshEditor *meshEditor, int vertexIndex1, int vertexIndex2)
Constructor with the associated meshEditor and the vertex indexes of the edge (vertexIndex1,...
Definition: qgsmesheditor.cpp:1116
QgsTopologicalMesh::edgeCanBeFlipped
bool edgeCanBeFlipped(int vertexIndex1, int vertexIndex2) const
Returns true if the edge can be flipped (only available for edge shared by two faces with 3 vertices)
Definition: qgstopologicalmesh.cpp:1915
QgsTriangularMesh::nativeFaceIndexForPoint
int nativeFaceIndexForPoint(const QgsPointXY &point) const
Finds index of native face at given point It uses spatial indexing.
Definition: qgstriangularmesh.cpp:427
QgsMeshEditor::createZValueDatasetGroup
QgsMeshDatasetGroup * createZValueDatasetGroup()
Creates and returns a scalar dataset group with value on vertex that is can be used to access the Z v...
Definition: qgsmesheditor.cpp:55
QgsMeshEditor::validVerticesCount
int validVerticesCount() const
Returns the count of valid vertices, that is non void vertices in the mesh.
Definition: qgsmesheditor.cpp:439
QgsPointXY::y
double y
Definition: qgspointxy.h:63
QgsMeshLayerUndoCommandAddVertices::QgsMeshLayerUndoCommandAddVertices
QgsMeshLayerUndoCommandAddVertices(QgsMeshEditor *meshEditor, const QVector< QgsMeshVertex > &vertices, double tolerance)
Constructor with the associated meshEditor and vertices that will be added.
Definition: qgsmesheditor.cpp:795
QgsMeshEditor::isVertexFree
bool isVertexFree(int vertexIndex) const
Returns whether the vertex with index vertexIndex is a free vertex.
Definition: qgsmesheditor.cpp:1004
QgsTriangularMesh::vertices
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
Definition: qgstriangularmesh.cpp:352
QgsTopologicalMesh::merge
Changes merge(int vertexIndex1, int vertexIndex2)
Merges faces separated by vertices with indexes vertexIndex1 and vertexIndex2 The method returns a in...
Definition: qgstopologicalmesh.cpp:2091
QgsMeshEditor::canBeTransformed
bool canBeTransformed(const QList< int > &facesToCheck, const std::function< const QgsMeshVertex(int)> &transformFunction) const
Returns true if faces with index in transformedFaces can be transformed without obtaining topologic o...
Definition: qgsmesheditor.cpp:636
QgsMeshLayerUndoCommandFlipEdge::redo
void redo() override
Definition: qgsmesheditor.cpp:1124
QgsTopologicalMesh::TopologicalFaces
Class that contains independent faces an topological information about this faces.
Definition: qgstopologicalmesh.h:62
QgsMeshEditor::faceCanBeSplit
bool faceCanBeSplit(int faceIndex) const
Returns true if face with index faceIndex can be split.
Definition: qgsmesheditor.cpp:486
QgsTopologicalMesh::addFreeVertex
Changes addFreeVertex(const QgsMeshVertex &vertex)
Adds a free vertex in the face, that is a vertex tha tis not included or linked with any faces.
Definition: qgstopologicalmesh.cpp:1112
Qgis::MeshEditingErrorType::FlatFace
@ FlatFace
A flat face is present.
QgsTopologicalMesh::Changes
Class that contains topological differences between two states of a topological mesh,...
Definition: qgstopologicalmesh.h:96
QgsGeometry::fromPolylineXY
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
Definition: qgsgeometry.cpp:186
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:48
QgsTopologicalMesh::canBeMerged
bool canBeMerged(int vertexIndex1, int vertexIndex2) const
Returns true if faces separated by vertices with indexes vertexIndex1 and vertexIndex2 can be merged.
Definition: qgstopologicalmesh.cpp:2048
QgsMeshVertex
QgsPoint QgsMeshVertex
xyz coords of vertex
Definition: qgsmeshdataprovider.h:36
QgsMeshLayerUndoCommandRemoveVerticesFillHoles::QgsMeshLayerUndoCommandRemoveVerticesFillHoles
QgsMeshLayerUndoCommandRemoveVerticesFillHoles(QgsMeshEditor *meshEditor, const QList< int > &verticesToRemoveIndexes, QList< int > *remainingVerticesPointer=nullptr)
Constructor with the associated meshEditor and vertices that will be removed.
Definition: qgsmesheditor.cpp:825
Qgis::MeshEditingErrorType
MeshEditingErrorType
Type of error that can occur during mesh frame editing.
Definition: qgis.h:734
QgsTriangularMesh::faceCentroids
const QVector< QgsMeshVertex > & faceCentroids() const
Returns centroids of the native faces in map CRS.
Definition: qgstriangularmesh.cpp:372
QgsMeshEditor::QgsMeshLayerUndoCommandSplitFaces
friend class QgsMeshLayerUndoCommandSplitFaces
Definition: qgsmesheditor.h:324
QgsMeshEditor::changeZValues
void changeZValues(const QList< int > &verticesIndexes, const QList< double > &newValues)
Changes the Z values of the vertices with indexes in vertices indexes with the values in newValues.
Definition: qgsmesheditor.cpp:631
QgsTriangularMesh::applyChanges
void applyChanges(const Changes &changes)
Applies the changes on the triangular mesh (see Changes)
Definition: qgstriangularmesh.cpp:724
QgsGeometryUtils::sqrDistToLine
static double sqrDistToLine(double ptX, double ptY, double x1, double y1, double x2, double y2, double &minDistX, double &minDistY, double epsilon) SIP_HOLDGIL
Returns the squared distance between a point and a line.
Definition: qgsgeometryutils.cpp:203
QgsTopologicalMesh::reverseChanges
void reverseChanges(const Changes &changes)
Reverses the changes.
Definition: qgstopologicalmesh.cpp:436
qgis.h
QgsMeshLayerUndoCommandMeshEdit::QgsMeshLayerUndoCommandMeshEdit
QgsMeshLayerUndoCommandMeshEdit(QgsMeshEditor *meshEditor)
Constructor for the base class.
Definition: qgsmesheditor.cpp:772
QgsTopologicalMesh::changeZValue
Changes changeZValue(const QList< int > &verticesIndexes, const QList< double > &newValues)
Changes the Z values of the vertices with indexes in vertices indexes with the values in newValues.
Definition: qgstopologicalmesh.cpp:2513
QgsMeshAdvancedEditing::text
virtual QString text() const
Returns a short text string describing what this advanced edit does. Default implementation return a ...
Definition: qgsmeshadvancedediting.cpp:60
QgsMeshEditor::freeVerticesIndexes
QList< int > freeVerticesIndexes() const
Returns all the free vertices indexes.
Definition: qgsmesheditor.cpp:994
QgsTriangularMesh::triangles
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
Definition: qgstriangularmesh.cpp:357
QgsMeshEditor::QgsMeshEditor
QgsMeshEditor(QgsMeshLayer *meshLayer)
Constructor with a specified layer meshLayer.
Definition: qgsmesheditor.cpp:33
QgsMesh
Mesh - vertices, edges and faces.
Definition: qgsmeshdataprovider.h:58
QgsMeshEditor::edgeIsClose
bool edgeIsClose(QgsPointXY point, double tolerance, int &faceIndex, int &edgePosition)
Returns true if an edge of face is closest than the tolerance from the point in triangular mesh coord...
Definition: qgsmesheditor.cpp:387
QgsLineString
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:44
QgsMeshLayerUndoCommandMeshEdit::mMeshEditor
QPointer< QgsMeshEditor > mMeshEditor
Definition: qgsmesheditor.h:349
QgsMeshVertexCirculator
Convenient class that turn around a vertex and provide information about faces and vertices.
Definition: qgstopologicalmesh.h:379
QgsMeshLayerUndoCommandSplitFaces::QgsMeshLayerUndoCommandSplitFaces
QgsMeshLayerUndoCommandSplitFaces(QgsMeshEditor *meshEditor, const QList< int > &faceIndexes)
Constructor with the associated meshEditor and indexes faceIndexes of the faces to split.
Definition: qgsmesheditor.cpp:1166
QgsMeshEditor::removeFaces
QgsMeshEditingError removeFaces(const QList< int > &facesToRemove)
Removes faces faces to the mesh, returns topological errors if this operation fails (operation is not...
Definition: qgsmesheditor.cpp:449
QgsMeshEditor::changeXYValues
void changeXYValues(const QList< int > &verticesIndexes, const QList< QgsPointXY > &newValues)
Changes the (X,Y) coordinates values of the vertices with indexes in verticesIndexes with the values ...
Definition: qgsmesheditor.cpp:750
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsTopologicalMesh::isVertexOnBoundary
bool isVertexOnBoundary(int vertexIndex) const
Returns whether the vertex is on a boundary.
Definition: qgstopologicalmesh.cpp:604
QgsMeshLayerUndoCommandRemoveVerticesFillHoles::redo
void redo() override
Definition: qgsmesheditor.cpp:836
QgsMeshLayerUndoCommandChangeZValue::QgsMeshLayerUndoCommandChangeZValue
QgsMeshLayerUndoCommandChangeZValue(QgsMeshEditor *meshEditor, const QList< int > &verticesIndexes, const QList< double > &newValues)
Constructor with the associated meshEditor and indexes verticesIndexes of the vertices that will have...
Definition: qgsmesheditor.cpp:1024
QgsMeshLayerUndoCommandAddFaces::redo
void redo() override
Definition: qgsmesheditor.cpp:912
QgsTopologicalMesh::facesAroundVertex
QList< int > facesAroundVertex(int vertexIndex) const
Returns the indexes of faces that are around the vertex with index vertexIndex.
Definition: qgstopologicalmesh.cpp:1782
QgsMeshEditor
Class that makes edit operation on a mesh.
Definition: qgsmesheditor.h:67
QgsTopologicalMesh::TopologicalFaces::meshFaces
QVector< QgsMeshFace > meshFaces() const
Returns faces.
Definition: qgstopologicalmesh.h:67
QgsTopologicalMesh
Class that wraps a QgsMesh to ensure the consistency of the mesh during editing and help to access to...
Definition: qgstopologicalmesh.h:47
QgsMeshLayerUndoCommandChangeCoordinates::QgsMeshLayerUndoCommandChangeCoordinates
QgsMeshLayerUndoCommandChangeCoordinates(QgsMeshEditor *meshEditor, const QList< int > &verticesIndexes, const QList< QgsPoint > &newCoordinates)
Constructor with the associated meshEditor and indexes verticesIndexes of the vertices that will have...
Definition: qgsmesheditor.cpp:1075
QgsMeshEditor::stopEditing
void stopEditing()
Stops editing.
Definition: qgsmesheditor.cpp:766
qgstriangularmesh.h
QgsPoint::y
double y
Definition: qgspoint.h:70
QgsMeshEditor::triangularMesh
QgsTriangularMesh * triangularMesh()
Returns a pointer to the triangular mesh.
Definition: qgsmesheditor.cpp:1019
QgsMeshLayerUndoCommandMerge::redo
void redo() override
Definition: qgsmesheditor.cpp:1149
QgsTopologicalMesh::flipEdge
Changes flipEdge(int vertexIndex1, int vertexIndex2)
Flips edge (vertexIndex1, vertexIndex2) The method returns a instance of the class QgsTopologicalMesh...
Definition: qgstopologicalmesh.cpp:1956
QgsMeshLayerUndoCommandRemoveFaces::QgsMeshLayerUndoCommandRemoveFaces
QgsMeshLayerUndoCommandRemoveFaces(QgsMeshEditor *meshEditor, const QList< int > &facesToRemoveIndexes)
Constructor with the associated meshEditor and indexes facesToRemoveIndexes of the faces that will be...
Definition: qgsmesheditor.cpp:929
QgsMeshEditor::addVertices
int addVertices(const QVector< QgsMeshVertex > &vertices, double tolerance)
Adds vertices in triangular mesh coordinate in the mesh.
Definition: qgsmesheditor.cpp:555
QgsMeshEditor::isModified
bool isModified() const
Returns whether the mesh has been modified.
Definition: qgsmesheditor.cpp:962
QgsTopologicalMesh::freeVerticesIndexes
QList< int > freeVerticesIndexes() const
Returns a list of vertices are not linked to any faces.
Definition: qgstopologicalmesh.cpp:625
QgsMeshLayerUndoCommandChangeXYValue::redo
void redo() override
Definition: qgsmesheditor.cpp:1057
qgsgeometryengine.h
QgsGeometry::intersects
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
Definition: qgsgeometry.cpp:1255
QgsMeshLayerUndoCommandMeshEdit::undo
void undo() override
Definition: qgsmesheditor.cpp:777
QgsMeshAdvancedEditing::isFinished
virtual bool isFinished() const
Returns whether the advanced edit is finished, if not, this edit has to be applied again with QgsMesh...
Definition: qgsmeshadvancedediting.cpp:55
QgsTriangularMesh::nativeExtent
QgsRectangle nativeExtent()
Returns the extent of the mesh in the native mesh coordinates system, returns empty extent if the tra...
Definition: qgstriangularmesh.cpp:287
QgsMesh::faceCount
int faceCount() const
Returns number of faces.
Definition: qgsmeshdataprovider.cpp:205
QgsMeshEditor::addFaces
QgsMeshEditingError addFaces(const QVector< QgsMeshFace > &faces)
Adds faces faces to the mesh, returns topological errors if this operation fails (operation is not re...
Definition: qgsmesheditor.cpp:530
QgsMesh::vertexCount
int vertexCount() const
Returns number of vertices.
Definition: qgsmeshdataprovider.cpp:200
QgsMeshEditor::QgsMeshLayerUndoCommandFlipEdge
friend class QgsMeshLayerUndoCommandFlipEdge
Definition: qgsmesheditor.h:322
QgsTopologicalMesh::canBeSplit
bool canBeSplit(int faceIndex) const
Returns true if face with index faceIndex can be split.
Definition: qgstopologicalmesh.cpp:2181
QgsMesh::faces
QVector< QgsMeshFace > faces
Definition: qgsmeshdataprovider.h:114
QgsTriangularMesh::nativeFaceIndexForRectangle
QList< int > nativeFaceIndexForRectangle(const QgsRectangle &rectangle) const
Finds indexes of native faces which bounding boxes intersect given bounding box It uses spatial index...
Definition: qgstriangularmesh.cpp:439
qgsmeshadvancedediting.h
QgsTopologicalMesh::changeXYValue
Changes changeXYValue(const QList< int > &verticesIndexes, const QList< QgsPointXY > &newValues)
Changes the (X,Y) values of the vertices with indexes in vertices indexes with the values in newValue...
Definition: qgstopologicalmesh.cpp:2532
QgsMeshEditor::QgsMeshLayerUndoCommandChangeZValue
friend class QgsMeshLayerUndoCommandChangeZValue
Definition: qgsmesheditor.h:319
QgsMeshLayer
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:98
QgsMeshEditor::validFacesCount
int validFacesCount() const
Returns the count of valid faces, that is non void faces in the mesh.
Definition: qgsmesheditor.cpp:434
QgsMeshEditor::advancedEdit
void advancedEdit(QgsMeshAdvancedEditing *editing)
Applies an advance editing on the edited mesh, see QgsMeshAdvancedEditing.
Definition: qgsmesheditor.cpp:761
QgsMeshEditor::extent
QgsRectangle extent() const
Returns the extent of the edited mesh.
Definition: qgsmesheditor.cpp:957
QgsMeshLayerUndoCommandSplitFaces::redo
void redo() override
Definition: qgsmesheditor.cpp:1173
QgsMeshEditingError
Class that represents an error during mesh editing.
Definition: qgsmesheditor.h:42
Qgis::MeshEditingErrorType::InvalidFace
@ InvalidFace
An error occurs due to an invalid face (for example, vertex indexes are unordered)
QgsTopologicalMesh::renumber
bool renumber()
Renumbers the indexes of vertices and faces using the Reverse CutHill McKee Algorithm.
Definition: qgstopologicalmesh.cpp:743
QgsMesh::face
QgsMeshFace face(int index) const
Returns a face at the index.
Definition: qgsmeshdataprovider.cpp:145
QgsMeshEditor::initialize
QgsMeshEditingError initialize()
Initialize the mesh editor and return errors if the internal native mesh have topologic errors.
Definition: qgsmesheditor.cpp:64
QgsMeshEditor::addFace
QgsMeshEditingError addFace(const QVector< int > &vertexIndexes)
Adds a face face to the mesh with vertex indexes vertexIndexes, returns topological errors if this op...
Definition: qgsmesheditor.cpp:550
QgsTopologicalMesh::removeVertices
Changes removeVertices(const QList< int > &vertices)
Removes all the vertices with index in the list vertices If vertices in linked with faces,...
Definition: qgstopologicalmesh.cpp:1472
QgsMeshEditor::addPointsAsVertices
int addPointsAsVertices(const QVector< QgsPoint > &point, double tolerance)
Adds points as vertices in triangular mesh coordinate in the mesh.
Definition: qgsmesheditor.cpp:598
QgsMeshLayerUndoCommandChangeCoordinates::redo
void redo() override
Definition: qgsmesheditor.cpp:1083
QgsMeshEditor::canBeMerged
bool canBeMerged(int vertexIndex1, int vertexIndex2) const
Returns true if faces separated by vertices with indexes vertexIndex1 and vertexIndex2 can be merged.
Definition: qgsmesheditor.cpp:473
QgsMeshLayerUndoCommandRemoveFaces::redo
void redo() override
Definition: qgsmesheditor.cpp:936
QgsTopologicalMesh::addVertexInFace
Changes addVertexInFace(int faceIndex, const QgsMeshVertex &vertex)
Adds a vertex in the face with index faceIndex.
Definition: qgstopologicalmesh.cpp:2264
Qgis::MeshEditingErrorType::InvalidVertex
@ InvalidVertex
An error occurs due to an invalid vertex (for example, vertex index is out of range the available ver...
QgsMeshEditor::edgeCanBeFlipped
bool edgeCanBeFlipped(int vertexIndex1, int vertexIndex2) const
Returns true if the edge can be flipped (only available for edge shared by two faces with 3 vertices)
Definition: qgsmesheditor.cpp:460
QgsTopologicalMesh::vertexCirculator
QgsMeshVertexCirculator vertexCirculator(int vertexIndex) const
Returns a vertex circulator linked to this mesh around the vertex with index vertexIndex.
Definition: qgstopologicalmesh.cpp:510
QgsTriangularMesh::faceIndexForPoint_v2
int faceIndexForPoint_v2(const QgsPointXY &point) const
Finds index of triangle at given point It uses spatial indexing and don't use geos to be faster.
Definition: qgstriangularmesh.cpp:447
QgsTopologicalMesh::removeVertexFillHole
Changes removeVertexFillHole(int vertexIndex)
Removes the vertex with index vertexIndex.
Definition: qgstopologicalmesh.cpp:1157
QgsTopologicalMesh::Changes::isEmpty
bool isEmpty() const
Returns whether changes are empty, that there is nothing to change.
Definition: qgstopologicalmesh.cpp:1044
QgsMeshFace
QVector< int > QgsMeshFace
List of vertex indexes.
Definition: qgsmeshdataprovider.h:42
QgsGeometry::constGet
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:136
QgsTopologicalMesh::checkConsistency
QgsMeshEditingError checkConsistency() const
Checks the consistency of the topological mesh and return false if there is a consistency issue.
Definition: qgstopologicalmesh.cpp:539
qgsmesheditor.h
QgsTopologicalMesh::insertVertexInFacesEdge
Changes insertVertexInFacesEdge(int faceIndex, int position, const QgsMeshVertex &vertex)
Inserts a vertex in the edge of face with index faceIndex at position .
Definition: qgstopologicalmesh.cpp:2327
QgsMeshEditor::QgsMeshLayerUndoCommandRemoveVerticesFillHoles
friend class QgsMeshLayerUndoCommandRemoveVerticesFillHoles
Definition: qgsmesheditor.h:315
QgsMeshDatasetGroup
Abstract class that represents a dataset group.
Definition: qgsmeshdataset.h:578
qgsgeometryutils.h
QgsMeshDataSourceInterface::maximumVerticesCountPerFace
virtual int maximumVerticesCountPerFace() const
Returns the maximum number of vertices per face supported by the current mesh, if returns 0,...
Definition: qgsmeshdataprovider.h:175
QgsMeshEditor::resetTriangularMesh
void resetTriangularMesh(QgsTriangularMesh *triangularMesh)
Resets the triangular mesh.
Definition: qgsmesheditor.cpp:73
qgsmeshlayer.h
QgsMeshEditor::removeVerticesFillHoles
QList< int > removeVerticesFillHoles(const QList< int > &verticesToRemoveIndexes)
Removes vertices with indexes in the list verticesToRemoveIndexes in the mesh the surrounding faces A...
Definition: qgsmesheditor.cpp:622
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
QgsMeshLayerUndoCommandRemoveVerticesWithoutFillHoles::QgsMeshLayerUndoCommandRemoveVerticesWithoutFillHoles
QgsMeshLayerUndoCommandRemoveVerticesWithoutFillHoles(QgsMeshEditor *meshEditor, const QList< int > &verticesToRemoveIndexes)
Constructor with the associated meshEditor and vertices that will be removed.
Definition: qgsmesheditor.cpp:878
QgsMeshEditor::QgsMeshLayerUndoCommandAdvancedEditing
friend class QgsMeshLayerUndoCommandAdvancedEditing
Definition: qgsmesheditor.h:326
QgsGeometry::createGeometryEngine
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
Definition: qgsgeometry.cpp:3972
QgsMeshLayerUndoCommandAdvancedEditing::redo
void redo() override
Definition: qgsmesheditor.cpp:1199
QgsTopologicalMesh::TopologicalFaces::clear
void clear()
Clears all data contained in the instance.
Definition: qgstopologicalmesh.cpp:1618
QgsGeometry::fromPolygonXY
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygonXY.
Definition: qgsgeometry.cpp:201
QgsMeshEditor::QgsMeshLayerUndoCommandMerge
friend class QgsMeshLayerUndoCommandMerge
Definition: qgsmesheditor.h:323
QgsTopologicalMesh::removeFaces
Changes removeFaces(const QList< int > facesIndexes)
Removes faces with index in faceIndexes.
Definition: qgstopologicalmesh.cpp:1808
QgsMeshEditor::QgsMeshLayerUndoCommandRemoveVerticesWithoutFillHoles
friend class QgsMeshLayerUndoCommandRemoveVerticesWithoutFillHoles
Definition: qgsmesheditor.h:314
QgsTopologicalMesh::splitFace
Changes splitFace(int faceIndex)
Splits face with index faceIndex The method returns a instance of the class QgsTopologicalMesh::Chang...
Definition: qgstopologicalmesh.cpp:2188
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsMeshEditor::meshEdited
void meshEdited()
Emitted when the mesh is edited.
Qgis::MeshEditingErrorType::ManifoldFace
@ ManifoldFace
ManifoldFace.
QgsMeshLayerUndoCommandMeshEdit
Base class for undo/redo command for mesh editing.
Definition: qgsmesheditor.h:338
QgsPointXY::x
double x
Definition: qgspointxy.h:62
QgsMeshEditor::splitFaces
int splitFaces(const QList< int > &faceIndexes)
Splits faces with index faceIndexes.
Definition: qgsmesheditor.cpp:491
QgsMeshEditor::QgsMeshLayerUndoCommandChangeCoordinates
friend class QgsMeshLayerUndoCommandChangeCoordinates
Definition: qgsmesheditor.h:321
QgsMeshLayerUndoCommandMerge::QgsMeshLayerUndoCommandMerge
QgsMeshLayerUndoCommandMerge(QgsMeshEditor *meshEditor, int vertexIndex1, int vertexIndex2)
Constructor with the associated meshEditor and the vertex indexes of the edge (vertexIndex1,...
Definition: qgsmesheditor.cpp:1141
QgsMeshLayerUndoCommandRemoveVerticesWithoutFillHoles::redo
void redo() override
Definition: qgsmesheditor.cpp:887
QgsMeshEditor::reindex
bool reindex(bool renumbering)
Reindexes the mesh, that is remove unusued index of face and vertices, this operation void the undo/r...
Definition: qgsmesheditor.cpp:970
QgsMeshLayerUndoCommandChangeXYValue::QgsMeshLayerUndoCommandChangeXYValue
QgsMeshLayerUndoCommandChangeXYValue(QgsMeshEditor *meshEditor, const QList< int > &verticesIndexes, const QList< QgsPointXY > &newValues)
Constructor with the associated meshEditor and indexes verticesIndexes of the vertices that will have...
Definition: qgsmesheditor.cpp:1049
QgsMeshEditor::QgsMeshLayerUndoCommandRemoveFaces
friend class QgsMeshLayerUndoCommandRemoveFaces
Definition: qgsmesheditor.h:317
QgsTopologicalMesh::Changes::verticesToRemoveIndexes
QList< int > verticesToRemoveIndexes() const
Returns the indexes of vertices to remove.
Definition: qgstopologicalmesh.cpp:1066
QgsTriangularMesh::triangularToNativeCoordinates
QgsMeshVertex triangularToNativeCoordinates(const QgsMeshVertex &vertex) const
Transforms the vertex from triangular mesh coordinates system to native coordinates system.
Definition: qgstriangularmesh.cpp:282
QgsMeshEditor::changeCoordinates
void changeCoordinates(const QList< int > &verticesIndexes, const QList< QgsPoint > &newCoordinates)
Changes the (X,Y,Z) coordinates values of the vertices with indexes in vertices indexes with the valu...
Definition: qgsmesheditor.cpp:756
QgsTopologicalMesh::addFaces
Changes addFaces(const TopologicalFaces &topologicFaces)
Adds faces topologicFaces to the topologic mesh.
Definition: qgstopologicalmesh.cpp:282
QgsMeshEditor::vertexCirculator
QgsMeshVertexCirculator vertexCirculator(int vertexIndex) const
Returns a vertex circulator linked to this mesh around the vertex with index vertexIndex.
Definition: qgsmesheditor.cpp:1009
QgsMeshLayerUndoCommandAddFaces::QgsMeshLayerUndoCommandAddFaces
QgsMeshLayerUndoCommandAddFaces(QgsMeshEditor *meshEditor, QgsTopologicalMesh::TopologicalFaces &faces)
Constructor with the associated meshEditor and faces that will be added.
Definition: qgsmesheditor.cpp:905
QgsMeshEditor::~QgsMeshEditor
~QgsMeshEditor()
QgsMeshLayerUndoCommandMeshEdit::mEdits
QList< QgsMeshEditor::Edit > mEdits
Definition: qgsmesheditor.h:350
QgsMeshEditor::isVertexOnBoundary
bool isVertexOnBoundary(int vertexIndex) const
Returns whether the vertex with index vertexIndex is on a boundary.
Definition: qgsmesheditor.cpp:999
QgsTopologicalMesh::createTopologicalMesh
static QgsTopologicalMesh createTopologicalMesh(QgsMesh *mesh, int maxVerticesPerFace, QgsMeshEditingError &error)
Creates a topologicaly consistent mesh with mesh, this static method modifies mesh to be topological ...
Definition: qgstopologicalmesh.cpp:1639
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:1080
Qgis
The Qgis class provides global constants for use throughout the application.
Definition: qgis.h:71
QgsTriangularMesh::Changes
The Changes class is used to make changes of the triangular and to keep traces of this changes If a C...
Definition: qgstriangularmesh.h:251
QgsTopologicalMesh::applyChanges
void applyChanges(const Changes &changes)
Applies the changes.
Definition: qgstopologicalmesh.cpp:354
QgsPoint::isEmpty
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
Definition: qgspoint.cpp:767
QgsMeshEditingError::errorType
Qgis::MeshEditingErrorType errorType
Definition: qgsmesheditor.h:52
Qgis::MeshEditingErrorType::TooManyVerticesInFace
@ TooManyVerticesInFace
A face has more vertices than the maximum number supported per face.
QgsTriangularMesh
Triangular/Derived Mesh is mesh with vertices in map coordinates.
Definition: qgstriangularmesh.h:51
QgsMeshEditor::merge
void merge(int vertexIndex1, int vertexIndex2)
Merges faces separated by vertices with indexes vertexIndex1 and vertexIndex2.
Definition: qgsmesheditor.cpp:478
QgsGeometry::contains
bool contains(const QgsPointXY *p) const
Returns true if the geometry contains the point p.
Definition: qgsgeometry.cpp:1303
QgsMeshEditor::QgsMeshLayerUndoCommandAddFaces
friend class QgsMeshLayerUndoCommandAddFaces
Definition: qgsmesheditor.h:316
QgsTopologicalMesh::createNewTopologicalFaces
static TopologicalFaces createNewTopologicalFaces(const QVector< QgsMeshFace > &faces, bool uniqueSharedVertexAllowed, QgsMeshEditingError &error)
Creates new topological faces that are not yet included in the mesh.
Definition: qgstopologicalmesh.cpp:1681
Qgis::MeshEditingErrorType::NoError
@ NoError
No type.
QgsMeshEditor::removeVerticesWithoutFillHoles
QgsMeshEditingError removeVerticesWithoutFillHoles(const QList< int > &verticesToRemoveIndexes)
Removes vertices with indexes in the list verticesToRemoveIndexes in the mesh removing the surroundin...
Definition: qgsmesheditor.cpp:603
QgsMeshUtils::toGeometry
CORE_EXPORT QgsGeometry toGeometry(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry.
Definition: qgstriangularmesh.cpp:638
qgslogger.h
QgsTopologicalMesh::Changes::addedFaces
QVector< QgsMeshFace > addedFaces() const
Returns the face that are added with this changes.
Definition: qgstopologicalmesh.cpp:999
QgsMeshLayerUndoCommandAdvancedEditing::QgsMeshLayerUndoCommandAdvancedEditing
QgsMeshLayerUndoCommandAdvancedEditing(QgsMeshEditor *meshEditor, QgsMeshAdvancedEditing *advancdEdit)
Constructor with the associated meshEditor.
Definition: qgsmesheditor.cpp:1192
QgsMeshEditor::checkConsistency
bool checkConsistency(QgsMeshEditingError &error) const
Return true if the edited mesh is consistent.
Definition: qgsmesheditor.cpp:362
QgsMeshDatasetGroup::setStatisticObsolete
void setStatisticObsolete() const
Sets statistic obsolete, that means statistic will be recalculated when requested.
Definition: qgsmeshdataset.cpp:981
QgsTopologicalMesh::counterClockwiseFaces
static QgsMeshEditingError counterClockwiseFaces(QgsMeshFace &face, QgsMesh *mesh)
Checks the topology of the face and sets it counter clockwise if necessary.
Definition: qgstopologicalmesh.cpp:634
QgsMeshEditor::flipEdge
void flipEdge(int vertexIndex1, int vertexIndex2)
Flips edge (vertexIndex1, vertexIndex2)
Definition: qgsmesheditor.cpp:465
QgsMeshLayerUndoCommandChangeZValue::redo
void redo() override
Definition: qgsmesheditor.cpp:1032
QgsTriangularMesh::reverseChanges
void reverseChanges(const Changes &changes, const QgsMesh &nativeMesh)
Reverses the changes on the triangular mesh (see Changes)
Definition: qgstriangularmesh.cpp:856
QgsMeshEditingError::QgsMeshEditingError
QgsMeshEditingError()
Constructor of the default error, that is NoError.
Definition: qgsmesheditor.cpp:953
QgsMeshEditor::isFaceGeometricallyCompatible
bool isFaceGeometricallyCompatible(const QgsMeshFace &face)
Returns true if the face does not intersect or contains any other elements (faces or vertices) The to...
Definition: qgsmesheditor.cpp:78
QgsMeshEditor::QgsMeshLayerUndoCommandChangeXYValue
friend class QgsMeshLayerUndoCommandChangeXYValue
Definition: qgsmesheditor.h:320
QgsTopologicalMesh::Changes::removedFaces
QVector< QgsMeshFace > removedFaces() const
Returns the faces that are removed with this changes.
Definition: qgstopologicalmesh.cpp:1004
QgsMeshAdvancedEditing::apply
virtual QgsTopologicalMesh::Changes apply(QgsMeshEditor *meshEditor)=0
Apply a change to mesh Editor.
QgsTopologicalMesh::facesCanBeRemoved
QgsMeshEditingError facesCanBeRemoved(const QList< int > facesIndexes)
Returns whether faces with index in faceIndexes can be removed/ The method an error object with type ...
Definition: qgstopologicalmesh.cpp:1789
qgsmeshdataprovider.h
QgsMeshEditor::topologicalMesh
QgsTopologicalMesh & topologicalMesh()
Returns a reference to the topological mesh.
Definition: qgsmesheditor.cpp:1014
QgsPoint::x
double x
Definition: qgspoint.h:69
QgsTopologicalMesh::reindex
void reindex()
Reindexes faces and vertices, after this operation, the topological mesh can't be edited anymore and ...
Definition: qgstopologicalmesh.cpp:693
QgsMeshLayer::dataProvider
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
Definition: qgsmeshlayer.cpp:110
QgsMeshLayerUndoCommandMeshEdit::redo
void redo() override
Definition: qgsmesheditor.cpp:786
QgsTopologicalMesh::facesCanBeAdded
QgsMeshEditingError facesCanBeAdded(const TopologicalFaces &topologicalFaces) const
Returns whether the faces can be added to the mesh.
Definition: qgstopologicalmesh.cpp:1499
QgsTriangularMesh::nativeToTriangularCoordinates
QgsMeshVertex nativeToTriangularCoordinates(const QgsMeshVertex &vertex) const
Transforms the vertex from native coordinates system to triangular mesh coordinates system.
Definition: qgstriangularmesh.cpp:277
Qgis::MeshEditingErrorType::UniqueSharedVertex
@ UniqueSharedVertex
A least two faces share only one vertices.
QgsMeshEditor::faceCanBeAdded
bool faceCanBeAdded(const QgsMeshFace &face)
Returns true if a face can be added to the mesh.
Definition: qgsmesheditor.cpp:167
QgsMeshEditor::maximumVerticesPerFace
int maximumVerticesPerFace() const
Returns the maximum count of vertices per face that the mesh can support.
Definition: qgsmesheditor.cpp:444
QgsMeshEditor::QgsMeshLayerUndoCommandAddVertices
friend class QgsMeshLayerUndoCommandAddVertices
Definition: qgsmesheditor.h:313
QgsMeshLayerUndoCommandAddVertices::redo
void redo() override
Definition: qgsmesheditor.cpp:803