mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-04 00:04:03 -04:00
Mesh editing: Select mesh element by polygon (#44739)
[feature] [mesh] Select mesh elements by polygon Default behavior: all touched (partially included element) will be selected (green rubber band) (default) Alt Modifier: only totally included elements will be selected (blue rubber band) (alt + drag)
This commit is contained in:
parent
ad8991facc
commit
781f484908
@ -923,6 +923,7 @@
|
||||
<file>themes/default/mIconFolderHomeParams.svg</file>
|
||||
<file>themes/default/mActionMeasureBearing.svg</file>
|
||||
<file>themes/default/mActionMeshDigitizing.svg</file>
|
||||
<file>themes/default/mActionMeshSelectPolygon.svg</file>
|
||||
<file>themes/default/mActionNewMeshLayer.svg</file>
|
||||
<file>themes/default/mIconGeometryCollectionLayer.svg</file>
|
||||
<file>themes/default/mIconGps.svg</file>
|
||||
|
1
images/themes/default/mActionMeshSelectPolygon.svg
Normal file
1
images/themes/default/mActionMeshSelectPolygon.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><g stroke-linecap="round"><g fill="none" stroke="#6d7281" stroke-width="1.003672" transform="matrix(1.013697 0 0 .98287877 -.369842 -.425299)"><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><path d="m1.1507031 1.0490189 5.9317031 5.9446938-5.9317031 5.8498513z" fill="#fce94f" stroke="#c4a000" stroke-linejoin="round" stroke-width="1.077"/><path d="m1.1507031 1.0490189h12.1643639l-6.2326608 5.9446938z" fill="#fce94f" stroke="#c4a000" stroke-linejoin="round" stroke-width="1.077"/><path d="m1.1507031 12.843564 5.9317031-5.8498513 6.2326608 5.8498513z" fill="#fce94f" stroke="#c4a000" stroke-linejoin="round" stroke-width="1.077"/><path d="m13.315067 12.843564-6.2326608-5.8498513 6.2326608-5.9446938z" fill="#fce94f" stroke="#c4a000" stroke-linejoin="round" stroke-width="1.077"/><path d="m13.315067 12.843564v-11.7945451h9.123273z" fill="#fce94f" stroke="#c4a000" stroke-linejoin="round" stroke-width="1.077"/><path d="m13.315067 12.843564 9.123273-11.7945451v11.7945451z" fill="#fce94f" stroke="#c4a000" stroke-linejoin="round" stroke-width="1.077"/><path d="m7.2 12.831149 6.115067.01242v4.344658l-6.0958115.03813z" fill="#fce94f" stroke="#c4a000" stroke-linejoin="round" stroke-width="1.077"/></g><g transform="translate(-1.136095 .227219)"><path d="m2.2867978.8218 7.66378 13.309544 7.3009022 1.30165 3.02866-4.572794 4.04061-9.7228-10.829921 4.0172z" fill="#e5e5e5" fill-opacity=".629771"/><path d="m2.2867978.8218 7.66378 13.309544 7.3009022 1.30165 3.369489-4.686413 4.04061-9.7227179-10.695993 4.1064706z" fill="none" stroke="#424242" stroke-dasharray="4 1"/></g><path d="m22.652743 15.6955-12.756464-6.9791 5.477553 13.6014 2.180887-3.5312 4.312159 4.7134 1.633122-1.5913-4.408599-4.6683 3.561343-1.5449z" style="fill:#fff;fill-rule:evenodd;stroke:#000;stroke-width:.7;stroke-linecap:round;stroke-linejoin:round"/></svg>
|
After Width: | Height: | Size: 2.0 KiB |
@ -92,6 +92,8 @@ QgsMapToolEditMeshFrame::QgsMapToolEditMeshFrame( QgsMapCanvas *canvas )
|
||||
{
|
||||
mActionDigitizing = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshDigitizing.svg" ) ), tr( "Digitize mesh elements" ) );
|
||||
mActionDigitizing->setCheckable( true );
|
||||
mActionSelectByPolygon = new QAction( QgsApplication::getThemePixmap( QStringLiteral( "/mActionMeshSelectPolygon.svg" ) ), tr( "Select mesh element by polygon" ) );
|
||||
mActionSelectByPolygon->setCheckable( true );
|
||||
|
||||
mActionRemoveVerticesFillingHole = new QAction( this );
|
||||
mActionDelaunayTriangulation = new QAction( tr( "Delaunay triangulation with selected vertices" ), this );
|
||||
@ -111,6 +113,14 @@ QgsMapToolEditMeshFrame::QgsMapToolEditMeshFrame( QgsMapCanvas *canvas )
|
||||
activateWithState( Digitizing );
|
||||
} );
|
||||
|
||||
connect( mActionSelectByPolygon, &QAction::toggled, this, [this]( bool checked )
|
||||
{
|
||||
if ( checked )
|
||||
activateWithState( SelectingByPolygon );
|
||||
else
|
||||
mSelectionBand->reset( QgsWkbTypes::PolygonGeometry );
|
||||
} );
|
||||
|
||||
connect( mActionDelaunayTriangulation, &QAction::triggered, this, [this]
|
||||
{
|
||||
if ( mCurrentEditor && mSelectedVertices.count() > 3 )
|
||||
@ -152,6 +162,12 @@ void QgsMapToolEditMeshFrame::activateWithState( State state )
|
||||
mCurrentState = state;
|
||||
}
|
||||
|
||||
void QgsMapToolEditMeshFrame::backToDigitizing()
|
||||
{
|
||||
activateWithState( Digitizing );
|
||||
mActionDigitizing->setChecked( true );
|
||||
}
|
||||
|
||||
QgsMapToolEditMeshFrame::~QgsMapToolEditMeshFrame()
|
||||
{
|
||||
deleteZvalueWidget();
|
||||
@ -160,13 +176,15 @@ QgsMapToolEditMeshFrame::~QgsMapToolEditMeshFrame()
|
||||
QList<QAction *> QgsMapToolEditMeshFrame::actions() const
|
||||
{
|
||||
return QList<QAction *>()
|
||||
<< mActionDigitizing;
|
||||
<< mActionDigitizing
|
||||
<< mActionSelectByPolygon;
|
||||
}
|
||||
|
||||
QList<QAction *> QgsMapToolEditMeshFrame::mapToolActions()
|
||||
{
|
||||
return QList<QAction *>()
|
||||
<< mActionDigitizing;
|
||||
<< mActionDigitizing
|
||||
<< mActionSelectByPolygon;
|
||||
}
|
||||
|
||||
void QgsMapToolEditMeshFrame::initialize()
|
||||
@ -215,12 +233,8 @@ void QgsMapToolEditMeshFrame::initialize()
|
||||
|
||||
if ( !mSelectionBand )
|
||||
mSelectionBand = new QgsRubberBand( mCanvas, QgsWkbTypes::PolygonGeometry );
|
||||
mSelectionBandPartiallyFillColor = QColor( 0, 215, 120, 63 );
|
||||
mSelectionBandPartiallyStrokeColor = QColor( 0, 204, 102, 100 );
|
||||
mSelectionBandTotalFillColor = QColor( 0, 120, 215, 63 );
|
||||
mSelectionBandTotalStrokeColor = QColor( 0, 102, 204, 100 );
|
||||
mSelectionBand->setFillColor( mSelectionBandTotalFillColor );
|
||||
mSelectionBand->setStrokeColor( mSelectionBandTotalStrokeColor );
|
||||
mSelectionBand->setFillColor( QColor( 254, 178, 76, 63 ) );
|
||||
mSelectionBand->setStrokeColor( QColor( 254, 58, 29, 100 ) );
|
||||
mSelectionBand->setZValue( 10 );
|
||||
|
||||
if ( !mSelectedFacesRubberband )
|
||||
@ -407,6 +421,7 @@ bool QgsMapToolEditMeshFrame::populateContextMenuWithEvent( QMenu *menu, QgsMapM
|
||||
case AddingNewFace:
|
||||
case Selecting:
|
||||
case MovingVertex:
|
||||
case SelectingByPolygon:
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -422,6 +437,7 @@ QgsMapTool::Flags QgsMapToolEditMeshFrame::flags() const
|
||||
case AddingNewFace:
|
||||
case Selecting:
|
||||
case MovingVertex:
|
||||
case SelectingByPolygon:
|
||||
return QgsMapTool::Flags();
|
||||
}
|
||||
|
||||
@ -442,7 +458,8 @@ void QgsMapToolEditMeshFrame::cadCanvasPressEvent( QgsMapMouseEvent *e )
|
||||
if ( e->button() == Qt::LeftButton )
|
||||
{
|
||||
mStartSelectionPos = e->pos();
|
||||
mSelectionBand->reset( QgsWkbTypes::PolygonGeometry );
|
||||
if ( mCurrentState != SelectingByPolygon )
|
||||
mSelectionBand->reset( QgsWkbTypes::PolygonGeometry );
|
||||
switch ( mCurrentState )
|
||||
{
|
||||
case Digitizing:
|
||||
@ -476,11 +493,11 @@ void QgsMapToolEditMeshFrame::cadCanvasPressEvent( QgsMapMouseEvent *e )
|
||||
mStartMovingPoint = mapVertexXY( mCurrentVertexIndex );
|
||||
mCanMovingStart = true;
|
||||
}
|
||||
mPreviousState = mCurrentState;
|
||||
break;
|
||||
case AddingNewFace:
|
||||
case Selecting:
|
||||
case MovingVertex:
|
||||
case SelectingByPolygon:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -499,7 +516,8 @@ void QgsMapToolEditMeshFrame::cadCanvasMoveEvent( QgsMapMouseEvent *e )
|
||||
|
||||
if ( mLeftButtonPressed &&
|
||||
mCurrentState != MovingVertex &&
|
||||
mCurrentState != AddingNewFace )
|
||||
mCurrentState != AddingNewFace &&
|
||||
mCurrentState != SelectingByPolygon )
|
||||
{
|
||||
if ( mCanMovingStart )
|
||||
{
|
||||
@ -526,18 +544,6 @@ void QgsMapToolEditMeshFrame::cadCanvasMoveEvent( QgsMapMouseEvent *e )
|
||||
case Selecting:
|
||||
{
|
||||
const QRect &rect = QRect( e->pos(), mStartSelectionPos );
|
||||
mSelectPartiallyContainedFace = e->pos().x() < mStartSelectionPos.x();
|
||||
if ( mSelectPartiallyContainedFace )
|
||||
{
|
||||
mSelectionBand->setFillColor( mSelectionBandPartiallyFillColor );
|
||||
mSelectionBand->setColor( mSelectionBandPartiallyStrokeColor );
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelectionBand->setFillColor( mSelectionBandTotalFillColor );
|
||||
mSelectionBand->setColor( mSelectionBandTotalStrokeColor );
|
||||
}
|
||||
|
||||
mSelectionBand->setToCanvasRectangle( rect );
|
||||
}
|
||||
break;
|
||||
@ -616,6 +622,9 @@ void QgsMapToolEditMeshFrame::cadCanvasMoveEvent( QgsMapMouseEvent *e )
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SelectingByPolygon:
|
||||
mSelectionBand->movePoint( mapPoint );
|
||||
break;
|
||||
}
|
||||
|
||||
QgsMapToolAdvancedDigitizing::cadCanvasMoveEvent( e );
|
||||
@ -729,10 +738,10 @@ void QgsMapToolEditMeshFrame::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
|
||||
break;
|
||||
case Selecting:
|
||||
{
|
||||
mCurrentState = mPreviousState;
|
||||
QgsGeometry selectionGeom = mSelectionBand->asGeometry();
|
||||
selectInGeometry( selectionGeom, e->modifiers() );
|
||||
mSelectionBand->reset( QgsWkbTypes::PolygonGeometry );
|
||||
mCurrentState = Digitizing;
|
||||
}
|
||||
break;
|
||||
case MovingVertex:
|
||||
@ -757,6 +766,19 @@ void QgsMapToolEditMeshFrame::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
|
||||
mMovingVerticesRubberband->reset();
|
||||
mCurrentState = Digitizing;
|
||||
break;
|
||||
case SelectingByPolygon:
|
||||
if ( e->button() == Qt::LeftButton )
|
||||
{
|
||||
mSelectionBand->movePoint( mapPoint );
|
||||
mSelectionBand->addPoint( mapPoint );
|
||||
}
|
||||
else if ( e->button() == Qt::RightButton )
|
||||
{
|
||||
QgsGeometry selectionGeom = mSelectionBand->asGeometry();
|
||||
selectInGeometry( selectionGeom, e->modifiers() );
|
||||
mSelectionBand->reset( QgsWkbTypes::PolygonGeometry );
|
||||
}
|
||||
break;
|
||||
}
|
||||
mDoubleClicks = false;
|
||||
|
||||
@ -878,8 +900,6 @@ bool QgsMapToolEditMeshFrame::testBorderMovingFace( const QgsMeshFace &borderMov
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void QgsMapToolEditMeshFrame::keyPressEvent( QKeyEvent *e )
|
||||
{
|
||||
bool consumned = false;
|
||||
@ -932,6 +952,20 @@ void QgsMapToolEditMeshFrame::keyPressEvent( QKeyEvent *e )
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SelectingByPolygon:
|
||||
if ( e->key() == Qt::Key_Escape )
|
||||
{
|
||||
mSelectionBand->reset( QgsWkbTypes::PolygonGeometry );
|
||||
backToDigitizing();
|
||||
consumned = true;
|
||||
}
|
||||
|
||||
if ( e->key() == Qt::Key_Backspace )
|
||||
{
|
||||
mSelectionBand->removePoint( -2, true );
|
||||
consumned = true;
|
||||
}
|
||||
break;
|
||||
case Selecting:
|
||||
case MovingVertex:
|
||||
break;
|
||||
@ -956,6 +990,7 @@ void QgsMapToolEditMeshFrame::keyReleaseEvent( QKeyEvent *e )
|
||||
case Digitizing:
|
||||
break;
|
||||
case AddingNewFace:
|
||||
case SelectingByPolygon:
|
||||
if ( e->key() == Qt::Key_Backspace )
|
||||
consumned = true; //to avoid removing the value of the ZvalueWidget
|
||||
break;
|
||||
@ -1270,7 +1305,7 @@ void QgsMapToolEditMeshFrame::selectInGeometry( const QgsGeometry &geometry, Qt:
|
||||
for ( const int faceIndex : nativeFaceIndexes )
|
||||
{
|
||||
const QgsMeshFace &face = nativeFace( faceIndex );
|
||||
if ( mSelectPartiallyContainedFace )
|
||||
if ( !( modifiers & Qt::AltModifier ) )
|
||||
{
|
||||
std::unique_ptr<QgsPolygon> faceGeom( new QgsPolygon( new QgsLineString( nativeFaceGeometry( faceIndex ) ) ) );
|
||||
if ( engine->intersects( faceGeom.get() ) )
|
||||
|
@ -102,7 +102,8 @@ class APP_EXPORT QgsMapToolEditMeshFrame : public QgsMapToolAdvancedDigitizing
|
||||
Digitizing, //!< Digitizing action can be start (add/remove vertices, selection, add/remove faces, move vertices)
|
||||
AddingNewFace, //!< Adding a face has been start and the user have to choose or digitize vertices
|
||||
Selecting, //!< Selection is in process
|
||||
MovingVertex //!< Moving vertex or vertices is processing
|
||||
MovingVertex, //!< Moving vertex or vertices is processing
|
||||
SelectingByPolygon, //!< Selection elements by polygon is in progress
|
||||
};
|
||||
|
||||
typedef QPair<int, int> Edge; //first face index, second the vertex index corresponding to the end extremity (ccw)
|
||||
@ -110,6 +111,7 @@ class APP_EXPORT QgsMapToolEditMeshFrame : public QgsMapToolAdvancedDigitizing
|
||||
// methods
|
||||
void initialize();
|
||||
void activateWithState( State state );
|
||||
void backToDigitizing();
|
||||
const QgsMeshVertex mapVertex( int index ) const;
|
||||
const QgsPointXY mapVertexXY( int index ) const;
|
||||
const QgsMeshFace nativeFace( int index ) const;
|
||||
@ -166,7 +168,6 @@ class APP_EXPORT QgsMapToolEditMeshFrame : public QgsMapToolAdvancedDigitizing
|
||||
|
||||
bool mIsInitialized = false;
|
||||
State mCurrentState = Digitizing;
|
||||
State mPreviousState = Digitizing; //used to store a state and restore it after a particular action as selecting
|
||||
bool mLeftButtonPressed = false;
|
||||
bool mKeepSelectionOnEdit = false;
|
||||
|
||||
@ -216,7 +217,6 @@ class APP_EXPORT QgsMapToolEditMeshFrame : public QgsMapToolAdvancedDigitizing
|
||||
QColor mSelectionBandTotalStrokeColor = QColor( 0, 102, 204, 100 );
|
||||
QgsRubberBand *mSelectedFacesRubberband = nullptr; //own by map canvas
|
||||
QMap< int, QgsVertexMarker * > mSelectedVerticesMarker;
|
||||
bool mSelectPartiallyContainedFace = false;
|
||||
|
||||
//! members for moving vertices
|
||||
QgsPointXY mStartMovingPoint;
|
||||
@ -246,6 +246,7 @@ class APP_EXPORT QgsMapToolEditMeshFrame : public QgsMapToolAdvancedDigitizing
|
||||
QAction *mActionFacesRefinement = nullptr;
|
||||
|
||||
QAction *mActionDigitizing = nullptr;
|
||||
QAction *mActionSelectByPolygon = nullptr;
|
||||
|
||||
friend class TestQgsMapToolEditMesh;
|
||||
};
|
||||
|
@ -191,15 +191,15 @@ void TestQgsMapToolEditMesh::editMesh()
|
||||
QCOMPARE( meshLayerQuadFlower->datasetValue( QgsMeshDatasetIndex( 0, 0 ), QgsPointXY( 2500, 3250 ) ).x(), 1500 );
|
||||
|
||||
//Selection
|
||||
// from left to right
|
||||
// completely included
|
||||
tool.mouseMove( 1200, 3600 );
|
||||
tool.mousePress( 1200, 3600, Qt::LeftButton );
|
||||
tool.mouseMove( 2700, 2250 );
|
||||
tool.mouseRelease( 2700, 2250, Qt::LeftButton );
|
||||
tool.mouseRelease( 2700, 2250, Qt::LeftButton, Qt::AltModifier );
|
||||
QCOMPARE( editMeshMapTool->mSelectedVertices.count(), 5 );
|
||||
QCOMPARE( editMeshMapTool->mSelectedFaces.count(), 1 );
|
||||
|
||||
// from left to right
|
||||
// touched
|
||||
tool.mouseMove( 2700, 2250 );
|
||||
tool.mousePress( 2700, 2250, Qt::LeftButton );
|
||||
tool.mouseMove( 1200, 3600 );
|
||||
@ -280,9 +280,43 @@ void TestQgsMapToolEditMesh::editMesh()
|
||||
tool.mouseClick( 1500, 3324, Qt::LeftButton );
|
||||
centroid = meshLayerQuadFlower->snapOnElement( QgsMesh::Face, QgsPointXY( 1100, 3050 ), 10 );
|
||||
QVERIFY( centroid.compare( QgsPointXY( 1500, 3100 ), 1e-2 ) );
|
||||
|
||||
tool.keyClick( Qt::Key_Escape );
|
||||
|
||||
QCOMPARE( editMeshMapTool->mSelectedVertices.count(), 0 );
|
||||
QCOMPARE( editMeshMapTool->mSelectedFaces.count(), 0 );
|
||||
|
||||
// Selection by polygon
|
||||
editMeshMapTool->mActionSelectByPolygon->trigger();
|
||||
|
||||
// touched
|
||||
tool.mouseClick( 3500, 3250, Qt::LeftButton );
|
||||
tool.mouseClick( 2750, 3250, Qt::LeftButton );
|
||||
tool.mouseClick( 1750, 2500, Qt::LeftButton );
|
||||
tool.mouseClick( 2500, 2000, Qt::LeftButton );
|
||||
tool.mouseClick( 3000, 2000, Qt::LeftButton );
|
||||
tool.mouseClick( 3000, 2000, Qt::RightButton );
|
||||
|
||||
QCOMPARE( editMeshMapTool->mSelectedVertices.count(), 5 );
|
||||
QCOMPARE( editMeshMapTool->mSelectedFaces.count(), 3 );
|
||||
|
||||
// completely included
|
||||
tool.mouseClick( 2750, 3250, Qt::LeftButton );
|
||||
tool.mouseClick( 3500, 3250, Qt::LeftButton );
|
||||
tool.mouseClick( 3000, 2000, Qt::LeftButton );
|
||||
tool.mouseClick( 2500, 2000, Qt::LeftButton );
|
||||
tool.mouseClick( 1750, 2500, Qt::LeftButton );
|
||||
tool.mouseClick( 1750, 2500, Qt::RightButton, Qt::AltModifier );
|
||||
|
||||
QCOMPARE( editMeshMapTool->mSelectedVertices.count(), 1 );
|
||||
QCOMPARE( editMeshMapTool->mSelectedFaces.count(), 0 );
|
||||
|
||||
tool.keyClick( Qt::Key_Escape );
|
||||
tool.keyClick( Qt::Key_Escape );
|
||||
|
||||
QCOMPARE( editMeshMapTool->mSelectedVertices.count(), 0 );
|
||||
QCOMPARE( editMeshMapTool->mSelectedFaces.count(), 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
QGSTEST_MAIN( TestQgsMapToolEditMesh )
|
||||
#include "testqgsmaptooleditmesh.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user