Skip to content
Permalink
Browse files
Select by existing geometries (#45006)
[mesh] [feature] mesh select  element by existing selected polygon
  • Loading branch information
vcloarec committed Sep 10, 2021
1 parent 87d42af commit 4e0d0f6692d7608c33b361805fc862b8a78ddf31
@@ -927,6 +927,8 @@
<file>themes/default/mActionMeshSelectExpression.svg</file>
<file>themes/default/mActionNewMeshLayer.svg</file>
<file>themes/default/mActionMeshTransformByExpression.svg</file>
<file>themes/default/mActionMeshSelectByTouchingGeometry.svg</file>
<file>themes/default/mActionMeshSelectByContainingGeometry.svg</file>
<file>themes/default/mIconVertexCoordinates.svg</file>
<file>themes/default/mActionMeshEditForceByVectorLines.svg</file>
<file>themes/default/mActionMeshReindex.svg</file>
@@ -0,0 +1 @@
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round"><path d="m11.985167 1.3595988-10.0115895 17.9748692m0 0h20.0231785m0 0-10.011589-17.9748692" fill="#fce94f" stroke="#5b6775" stroke-linejoin="bevel" stroke-width="1.002"/><g stroke="#c4a000" stroke-linejoin="round" stroke-width=".933968" transform="matrix(1.0707604 0 0 1.0706405 -48.994616 4.657768)"><path d="m50.730049 2.8451652-.18235 12.6360258h10.492628l3.839717-12.8620523z" fill="none"/><path d="m52.311948 2.8451652c0 2.1564332-3.162859 2.1564332-3.162859 0 0-2.15643314 3.162859-2.15643314 3.162859 0zm-.0048 12.6504958c0 2.156432-3.162859 2.156432-3.162859 0 0-2.156433 3.162859-2.156433 3.162859 0zm10.370845-.04968c0 2.156433-3.162857 2.156433-3.162857 0 0-2.156434 3.162857-2.156434 3.162857 0zm3.894613-12.4844338c0 2.1564332-3.162859 2.1564332-3.162859 0 0-2.15643304 3.162859-2.15643304 3.162859 0z" fill="#eeeeec" fill-rule="evenodd"/></g><path d="m16.990961 10.347034h-10.0115888l5.0057948 8.987432z" fill="#fce94f" stroke="#5b6775" stroke-linejoin="bevel" stroke-width="1.001575"/></g></svg>
@@ -0,0 +1 @@
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m1.9735772 19.334469h20.0231788l-10.011589-17.9748703z" fill="#fce94f"/><g stroke-linecap="round"><path d="m11.985167 1.3595988-10.0115895 17.9748692m0 0h20.0231785m0 0-10.011589-17.9748692" fill="#fce94f" stroke="#5b6775" stroke-linejoin="bevel" stroke-width="1.002"/><g stroke="#c4a000" stroke-linejoin="round" stroke-width=".933968" transform="matrix(1.0707604 0 0 1.0706405 -48.994616 4.657768)"><path d="m50.730049 2.8451652-.18235 12.6360258h10.492628l3.839717-12.8620523z" fill="none"/><path d="m52.311948 2.8451652c0 2.1564332-3.162859 2.1564332-3.162859 0 0-2.15643314 3.162859-2.15643314 3.162859 0zm-.0048 12.6504958c0 2.156432-3.162859 2.156432-3.162859 0 0-2.156433 3.162859-2.156433 3.162859 0zm10.370845-.04968c0 2.156433-3.162857 2.156433-3.162857 0 0-2.156434 3.162857-2.156434 3.162857 0zm3.894613-12.4844338c0 2.1564332-3.162859 2.1564332-3.162859 0 0-2.15643304 3.162859-2.15643304 3.162859 0z" fill="#eeeeec" fill-rule="evenodd"/></g><path d="m16.990961 10.347034h-10.0115888l5.0057948 8.987432z" fill="#fce94f" stroke="#5b6775" stroke-linejoin="bevel" stroke-width="1.001575"/></g></svg>
@@ -206,30 +206,41 @@ QgsMapToolEditMeshFrame::QgsMapToolEditMeshFrame( QgsMapCanvas *canvas )
: QgsMapToolAdvancedDigitizing( canvas, QgisApp::instance()->cadDockWidget() )
, mSnapIndicator( new QgsSnapIndicator( canvas ) )
{
mActionDigitizing = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshDigitizing.svg" ) ), tr( "Digitize mesh elements" ), this );
mActionDigitizing = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshDigitizing.svg" ) ), tr( "Digitize Mesh elements" ), this );
mActionDigitizing->setCheckable( true );
mActionSelectByPolygon = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshSelectPolygon.svg" ) ), tr( "Select mesh element by polygon" ), this );
mActionSelectByPolygon = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshSelectPolygon.svg" ) ), tr( "Select mesh elements by polygon" ), this );
mActionSelectByPolygon->setCheckable( true );
mActionSelectByExpression = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshSelectExpression.svg" ) ), tr( "Select mesh elements by expression" ), this );

mActionTransformCoordinates = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshTransformByExpression.svg" ) ), tr( "Transform vertices coordinates" ), this );
mActionSelectByPolygon = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshSelectPolygon.svg" ) ), tr( "Select Mesh Elements by Polygon" ), this );
mActionSelectByPolygon->setCheckable( true );
mActionSelectByPolygon->setObjectName( QStringLiteral( "ActionMeshSelectByPolygon" ) );
mActionSelectByExpression = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshSelectExpression.svg" ) ), tr( "Select Mesh Elements by Expression" ), this );
mActionSelectByExpression->setObjectName( QStringLiteral( "ActionMeshSelectByExpression" ) );
mActionSelectByContainingSelectedPolygon = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshSelectByContainingGeometry.svg" ) ), tr( "Select Contained Elements by Selected Polygons" ), this );
mActionSelectByTouchingSelectedPolygon = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshSelectByTouchingGeometry.svg" ) ), tr( "Select Touched Elements by Selected Polygons" ), this );
mActionSelectByContainingSelectedPolygon->setEnabled( false );
mActionSelectByTouchingSelectedPolygon->setEnabled( false );

mSelectActions << mActionSelectByPolygon
<< mActionSelectByExpression
<< mActionSelectByContainingSelectedPolygon
<< mActionSelectByTouchingSelectedPolygon;

mActionTransformCoordinates = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshTransformByExpression.svg" ) ), tr( "Transform Vertices Coordinates" ), this );
mActionTransformCoordinates->setCheckable( true );

mActionForceByVectorLayerGeometries = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshEditForceByVectorLines.svg" ) ), tr( "Force by selected geometries" ), this );
mActionForceByVectorLayerGeometries = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshEditForceByVectorLines.svg" ) ), tr( "Force by Selected Geometries" ), this );
mActionForceByVectorLayerGeometries->setEnabled( areGeometriesSelectedInVectorLayer() );

mWidgetActionForceByLine = new QgsMeshEditForceByLineAction( this );
mWidgetActionForceByLine->setMapCanvas( canvas );

mActionReindexMesh = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshReindex.svg" ) ), tr( "Reindex faces and vertices" ), this );
mActionReindexMesh = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshReindex.svg" ) ), tr( "Reindex Faces and Vertices" ), this );

mActionRemoveVerticesFillingHole = new QAction( this );
mActionDelaunayTriangulation = new QAction( tr( "Delaunay triangulation with selected vertices" ), this );
mActionFacesRefinement = new QAction( tr( "Refine current face" ), this );
mActionDelaunayTriangulation = new QAction( tr( "Delaunay Triangulation with Selected Vertices" ), this );
mActionFacesRefinement = new QAction( tr( "Refine Current Face" ), this );
mActionRemoveVerticesWithoutFillingHole = new QAction( this );
mActionRemoveFaces = new QAction( tr( "Remove current face" ), this );
mActionSplitFaces = new QAction( tr( "Split current face" ), this );
mActionRemoveFaces = new QAction( tr( "Remove Current Face" ), this );
mActionSplitFaces = new QAction( tr( "Split Current Face" ), this );

connect( mActionRemoveVerticesFillingHole, &QAction::triggered, this, [this] {removeSelectedVerticesFromMesh( true );} );
connect( mActionRemoveVerticesWithoutFillingHole, &QAction::triggered, this, [this] {removeSelectedVerticesFromMesh( false );} );
@@ -242,14 +253,30 @@ QgsMapToolEditMeshFrame::QgsMapToolEditMeshFrame( QgsMapCanvas *canvas )
activateWithState( Digitizing );
} );

connect( mActionSelectByPolygon, &QAction::toggled, this, [this]( bool checked )
for ( int i = 0; i < mSelectActions.count(); ++i )
{
if ( checked )
connect( mSelectActions.at( i ), &QAction::triggered, this, [i]
{
QgsSettings settings;
settings.setValue( QStringLiteral( "UI/Mesh/defaultSelection" ), i );
} );
}

connect( mActionSelectByPolygon, &QAction::triggered, this, [this]
{
if ( mActionSelectByPolygon->isChecked() )
{
activateWithState( SelectingByPolygon );
}
else
mSelectionBand->reset( QgsWkbTypes::PolygonGeometry );
} );


connect( mActionSelectByExpression, &QAction::triggered, this, &QgsMapToolEditMeshFrame::showSelectByExpressionDialog );
connect( mActionSelectByTouchingSelectedPolygon, &QAction::triggered, this, &QgsMapToolEditMeshFrame::selectByTouchingSelectedPolygons );
connect( mActionSelectByContainingSelectedPolygon, &QAction::triggered, this, &QgsMapToolEditMeshFrame::selectByContainingSelectedPolygons );

connect( mActionDelaunayTriangulation, &QAction::triggered, this, [this]
{
if ( mCurrentEditor && mSelectedVertices.count() >= 3 )
@@ -280,11 +307,12 @@ QgsMapToolEditMeshFrame::QgsMapToolEditMeshFrame( QgsMapCanvas *canvas )

connect( mActionTransformCoordinates, &QAction::triggered, this, &QgsMapToolEditMeshFrame::triggerTransformCoordinatesDockWidget );

connect( mActionSelectByExpression, &QAction::triggered, this, &QgsMapToolEditMeshFrame::showSelectByExpressionDialog );

connect( canvas, &QgsMapCanvas::selectionChanged, this, [this]
{
mActionForceByVectorLayerGeometries->setEnabled( areGeometriesSelectedInVectorLayer() &&( mCurrentEditor != nullptr ) );
bool enable = areGeometriesSelectedInVectorLayer() && ( mCurrentEditor != nullptr );
mActionForceByVectorLayerGeometries->setEnabled( enable );
mActionSelectByContainingSelectedPolygon->setEnabled( enable );
mActionSelectByTouchingSelectedPolygon->setEnabled( enable );
} );

connect( mActionForceByVectorLayerGeometries, &QAction::triggered, this, &QgsMapToolEditMeshFrame::forceBySelectedLayerPolyline );
@@ -330,7 +358,10 @@ void QgsMapToolEditMeshFrame::setActionsEnable( bool enable )
for ( QAction *action : std::as_const( actions ) )
action->setEnabled( enable );

mActionForceByVectorLayerGeometries->setEnabled( enable && areGeometriesSelectedInVectorLayer() );
bool areGeometriesSelected = areGeometriesSelectedInVectorLayer();
mActionForceByVectorLayerGeometries->setEnabled( enable && areGeometriesSelected );
mActionSelectByContainingSelectedPolygon->setEnabled( enable && areGeometriesSelected );
mActionSelectByTouchingSelectedPolygon->setEnabled( enable && areGeometriesSelected );
}


@@ -348,12 +379,18 @@ QAction *QgsMapToolEditMeshFrame::digitizeAction() const

QList<QAction *> QgsMapToolEditMeshFrame::selectActions() const
{
return QList<QAction *>()
<< mActionSelectByPolygon;
return mSelectActions;
}

QAction *QgsMapToolEditMeshFrame::defaultSelectActions() const
{
QgsSettings settings;
bool ok = false;
int defaultIndex = settings.value( QStringLiteral( "UI/Mesh/defaultSelection" ) ).toInt( &ok );

if ( ok && mSelectActions.at( defaultIndex )->isEnabled() )
return mSelectActions.at( defaultIndex );

return mActionSelectByPolygon;
}

@@ -926,7 +963,7 @@ void QgsMapToolEditMeshFrame::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
case Selecting:
{
QgsGeometry selectionGeom = mSelectionBand->asGeometry();
selectInGeometry( selectionGeom, e->modifiers() );
selectByGeometry( selectionGeom, e->modifiers() );
mSelectionBand->reset( QgsWkbTypes::PolygonGeometry );
mCurrentState = Digitizing;
}
@@ -967,7 +1004,7 @@ void QgsMapToolEditMeshFrame::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
else if ( e->button() == Qt::RightButton )
{
QgsGeometry selectionGeom = mSelectionBand->asGeometry();
selectInGeometry( selectionGeom, e->modifiers() );
selectByGeometry( selectionGeom, e->modifiers() );
mSelectionBand->reset( QgsWkbTypes::PolygonGeometry );
}
break;
@@ -1651,11 +1688,27 @@ void QgsMapToolEditMeshFrame::reindexMesh()
mCurrentLayer->reindex( transform, true );
}

void QgsMapToolEditMeshFrame::selectInGeometry( const QgsGeometry &geometry, Qt::KeyboardModifiers modifiers )
void QgsMapToolEditMeshFrame::selectByGeometry( const QgsGeometry &geometry, Qt::KeyboardModifiers modifiers )
{
if ( mCurrentLayer.isNull() || !mCurrentLayer->triangularMesh() || mCurrentEditor.isNull() )
return;

Qgis::SelectBehavior behavior;
if ( modifiers & Qt::ShiftModifier )
behavior = Qgis::SelectBehavior::RemoveFromSelection;
else if ( modifiers & Qt::ControlModifier )
behavior = Qgis::SelectBehavior::RemoveFromSelection;
else
behavior = Qgis::SelectBehavior::SetSelection;

if ( modifiers & Qt::AltModifier )
selectContainedByGeometry( geometry, behavior );
else
selectTouchedByGeometry( geometry, behavior );
}

void QgsMapToolEditMeshFrame::selectTouchedByGeometry( const QgsGeometry &geometry, Qgis::SelectBehavior behavior )
{
QSet<int> selectedVertices;
const QList<int> nativeFaceIndexes = mCurrentLayer->triangularMesh()->nativeFaceIndexForRectangle( geometry.boundingBox() );

@@ -1665,26 +1718,43 @@ void QgsMapToolEditMeshFrame::selectInGeometry( const QgsGeometry &geometry, Qt:
for ( const int faceIndex : nativeFaceIndexes )
{
const QgsMeshFace &face = nativeFace( faceIndex );
if ( !( modifiers & Qt::AltModifier ) )
std::unique_ptr<QgsPolygon> faceGeom( new QgsPolygon( new QgsLineString( nativeFaceGeometry( faceIndex ) ) ) );
if ( engine->intersects( faceGeom.get() ) )
{
std::unique_ptr<QgsPolygon> faceGeom( new QgsPolygon( new QgsLineString( nativeFaceGeometry( faceIndex ) ) ) );
if ( engine->intersects( faceGeom.get() ) )
{
QSet<int> faceToAdd = qgis::listToSet( face.toList() );
selectedVertices.unite( faceToAdd );
}
QSet<int> faceToAdd = qgis::listToSet( face.toList() );
selectedVertices.unite( faceToAdd );
}
else
}

const QList<int> &freeVerticesIndexes = mCurrentEditor->freeVerticesIndexes();
for ( const int freeVertexIndex : freeVerticesIndexes )
{
const QgsMeshVertex &vertex = mapVertex( freeVertexIndex );
if ( engine->contains( &vertex ) )
selectedVertices.insert( freeVertexIndex );
}

setSelectedVertices( selectedVertices.values(), behavior );
}

void QgsMapToolEditMeshFrame::selectContainedByGeometry( const QgsGeometry &geometry, Qgis::SelectBehavior behavior )
{
QSet<int> selectedVertices;
const QList<int> nativeFaceIndexes = mCurrentLayer->triangularMesh()->nativeFaceIndexForRectangle( geometry.boundingBox() );

std::unique_ptr<QgsGeometryEngine> engine( QgsGeometry::createGeometryEngine( geometry.constGet() ) );
engine->prepareGeometry();
for ( const int faceIndex : nativeFaceIndexes )
{
const QgsMeshFace &face = nativeFace( faceIndex );
for ( const int vertexIndex : face )
{
for ( const int vertexIndex : face )
{
const QgsMeshVertex &vertex = mapVertex( vertexIndex );
if ( engine->contains( &vertex ) )
selectedVertices.insert( vertexIndex );
}
const QgsMeshVertex &vertex = mapVertex( vertexIndex );
if ( engine->contains( &vertex ) )
selectedVertices.insert( vertexIndex );
}
}
//free vertices

const QList<int> &freeVerticesIndexes = mCurrentEditor->freeVerticesIndexes();
for ( const int freeVertexIndex : freeVerticesIndexes )
{
@@ -1693,17 +1763,25 @@ void QgsMapToolEditMeshFrame::selectInGeometry( const QgsGeometry &geometry, Qt:
selectedVertices.insert( freeVertexIndex );
}

Qgis::SelectBehavior behavior;
if ( modifiers & Qt::ShiftModifier )
behavior = Qgis::SelectBehavior::RemoveFromSelection;
else if ( modifiers & Qt::ControlModifier )
behavior = Qgis::SelectBehavior::RemoveFromSelection;
else
behavior = Qgis::SelectBehavior::SetSelection;

setSelectedVertices( selectedVertices.values(), behavior );
}

void QgsMapToolEditMeshFrame::selectByTouchingSelectedPolygons()
{
onEditingStarted();
const QList<QgsGeometry> geometries = selectedGeometriesInVectorLayers();
for ( const QgsGeometry &geom : geometries )
selectTouchedByGeometry( geom, Qgis::SelectBehavior::AddToSelection );
}

void QgsMapToolEditMeshFrame::selectByContainingSelectedPolygons()
{
onEditingStarted();
const QList<QgsGeometry> geometries = selectedGeometriesInVectorLayers();
for ( const QgsGeometry &geom : geometries )
selectContainedByGeometry( geom, Qgis::SelectBehavior::AddToSelection );
}

void QgsMapToolEditMeshFrame::applyZValueOnSelectedVertices()
{
if ( !mZValueWidget )
@@ -2412,7 +2490,6 @@ int QgsMapToolEditMeshFrame::closeVertex( const QgsPointXY &mapPoint ) const
return -1;
}


void QgsMapToolEditMeshFrame::selectByExpression( const QString &textExpression, Qgis::SelectBehavior behavior, QgsMesh::ElementType elementType )
{
if ( !mCurrentEditor || !mCurrentLayer )
@@ -2440,6 +2517,7 @@ void QgsMapToolEditMeshFrame::selectByExpression( const QString &textExpression,
}
}


void QgsMapToolEditMeshFrame::onZoomToSelected()
{
canvas()->zoomToFeatureExtent( mSelectedMapExtent );
@@ -164,6 +164,8 @@ class APP_EXPORT QgsMapToolEditMeshFrame : public QgsMapToolAdvancedDigitizing

void showSelectByExpressionDialog();
void selectByExpression( const QString &textExpression, Qgis::SelectBehavior behavior, QgsMesh::ElementType elementType );
void selectByTouchingSelectedPolygons();
void selectByContainingSelectedPolygons();
void onZoomToSelected();
void forceBySelectedLayerPolyline();
void reindexMesh();
@@ -226,7 +228,9 @@ class APP_EXPORT QgsMapToolEditMeshFrame : public QgsMapToolAdvancedDigitizing
bool isFaceSelected( int faceIndex );
void setSelectedVertices( const QList<int> newSelectedVertices, Qgis::SelectBehavior behavior );
void setSelectedFaces( const QList<int> newSelectedFaces, Qgis::SelectBehavior behavior );
void selectInGeometry( const QgsGeometry &geometry, Qt::KeyboardModifiers modifiers );
void selectByGeometry( const QgsGeometry &geometry, Qt::KeyboardModifiers modifiers );
void selectTouchedByGeometry( const QgsGeometry &geometry, Qgis::SelectBehavior behavior );
void selectContainedByGeometry( const QgsGeometry &geometry, Qgis::SelectBehavior behavior );
void applyZValueOnSelectedVertices();
void prepareSelection();
void updateSelectecVerticesMarker();
@@ -282,6 +286,7 @@ class APP_EXPORT QgsMapToolEditMeshFrame : public QgsMapToolAdvancedDigitizing
QList<QgsVertexMarker *> mFreeVertexMarker;

//! members for selection of vertices/faces
QList<QAction *> mSelectActions;
QMap<int, SelectedVertexData> mSelectedVertices;
QgsRectangle mSelectedMapExtent;
QSet<int> mSelectedFaces;
@@ -333,6 +338,9 @@ class APP_EXPORT QgsMapToolEditMeshFrame : public QgsMapToolAdvancedDigitizing

QAction *mActionSelectByExpression = nullptr;
QAction *mActionForceByVectorLayerGeometries = nullptr;
QAction *mActionSelectByContainingSelectedPolygon = nullptr;
QAction *mActionSelectByTouchingSelectedPolygon = nullptr;

QgsMeshEditForceByLineAction *mWidgetActionForceByLine = nullptr;
QAction *mActionReindexMesh = nullptr;

0 comments on commit 4e0d0f6

Please sign in to comment.