mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-15 00:02:52 -04:00
Merge pull request #57584 from nirvn/cad_construction_guides
[advanced digitizing] Implement visual construction guides
This commit is contained in:
commit
2fb1de2ce1
@ -132,7 +132,6 @@ Returns the recent CAD point at the specified ``index`` (in map coordinates).
|
||||
|
||||
.. versionadded:: 3.22
|
||||
%End
|
||||
|
||||
%Property( name = cadPointList, get = _cadPointList, set = _setCadPointList )
|
||||
void _setCadPointList( const QList< QgsPointXY > &list );
|
||||
QList< QgsPointXY > _cadPointList() const;
|
||||
|
@ -277,7 +277,36 @@ Sets whether M is enabled
|
||||
|
||||
bool constructionMode() const;
|
||||
%Docstring
|
||||
construction mode is used to draw intermediate points. These points won't be given any further (i.e. to the map tools)
|
||||
Returns whether the construction mode is activated. The construction mode is used to draw intermediate
|
||||
points that will not be part of a geometry being digitized.
|
||||
%End
|
||||
|
||||
QgsVectorLayer *constructionGuidesLayer() const;
|
||||
%Docstring
|
||||
Returns the vector layer within which construction guides are stored.
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
bool showConstructionGuides() const;
|
||||
%Docstring
|
||||
Returns whether the construction guides are visible.
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
bool snapToConstructionGuides() const;
|
||||
%Docstring
|
||||
Returns whether points should snap to construction guides.
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
bool recordConstructionGuides() const;
|
||||
%Docstring
|
||||
Returns whether construction guides are being recorded.
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
Qgis::BetweenLineConstraint betweenLineConstraint() const;
|
||||
|
@ -132,7 +132,6 @@ Returns the recent CAD point at the specified ``index`` (in map coordinates).
|
||||
|
||||
.. versionadded:: 3.22
|
||||
%End
|
||||
|
||||
%Property( name = cadPointList, get = _cadPointList, set = _setCadPointList )
|
||||
void _setCadPointList( const QList< QgsPointXY > &list );
|
||||
QList< QgsPointXY > _cadPointList() const;
|
||||
|
@ -277,7 +277,36 @@ Sets whether M is enabled
|
||||
|
||||
bool constructionMode() const;
|
||||
%Docstring
|
||||
construction mode is used to draw intermediate points. These points won't be given any further (i.e. to the map tools)
|
||||
Returns whether the construction mode is activated. The construction mode is used to draw intermediate
|
||||
points that will not be part of a geometry being digitized.
|
||||
%End
|
||||
|
||||
QgsVectorLayer *constructionGuidesLayer() const;
|
||||
%Docstring
|
||||
Returns the vector layer within which construction guides are stored.
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
bool showConstructionGuides() const;
|
||||
%Docstring
|
||||
Returns whether the construction guides are visible.
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
bool snapToConstructionGuides() const;
|
||||
%Docstring
|
||||
Returns whether points should snap to construction guides.
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
bool recordConstructionGuides() const;
|
||||
%Docstring
|
||||
Returns whether construction guides are being recorded.
|
||||
|
||||
.. versionadded:: 3.40
|
||||
%End
|
||||
|
||||
Qgis::BetweenLineConstraint betweenLineConstraint() const;
|
||||
|
@ -48,8 +48,8 @@ QgsCadUtils::AlignMapPointOutput QgsCadUtils::alignMapPoint( const QgsPointXY &o
|
||||
res.softLockX = std::numeric_limits<double>::quiet_NaN();
|
||||
res.softLockY = std::numeric_limits<double>::quiet_NaN();
|
||||
|
||||
// try to snap to anything
|
||||
const QgsPointLocator::Match snapMatch = ctx.snappingUtils->snapToMap( originalMapPoint, nullptr, true );
|
||||
// try to snap to project layer(s) as well as visible construction guides
|
||||
QgsPointLocator::Match snapMatch = ctx.snappingUtils->snapToMap( originalMapPoint, nullptr, true );
|
||||
res.snapMatch = snapMatch;
|
||||
QgsPointXY point = snapMatch.isValid() ? snapMatch.point() : originalMapPoint;
|
||||
QgsPointXY edgePt0, edgePt1;
|
||||
|
@ -195,7 +195,6 @@ class CORE_EXPORT QgsCadUtils
|
||||
*/
|
||||
QQueue< QgsPointLocator::Match > lockedSnapVertices() const { return mLockedSnapVertices; } SIP_SKIP;
|
||||
|
||||
|
||||
#ifdef SIP_RUN
|
||||
SIP_PROPERTY( name = cadPointList, get = _cadPointList, set = _setCadPointList )
|
||||
#endif
|
||||
|
@ -28,6 +28,7 @@ QgsAdvancedDigitizingCanvasItem::QgsAdvancedDigitizingCanvasItem( QgsMapCanvas *
|
||||
, mSnapPen( QPen( QColor( 127, 0, 0, 150 ), 1 ) )
|
||||
, mSnapLinePen( QPen( QColor( 127, 0, 0, 150 ), 1, Qt::DashLine ) )
|
||||
, mCursorPen( QPen( QColor( 127, 127, 127, 255 ), 1 ) )
|
||||
, mConstructionGuidesPen( QPen( QColor( 20, 210, 150 ), 1, Qt::DashLine ) )
|
||||
, mAdvancedDigitizingDockWidget( cadDockWidget )
|
||||
{
|
||||
}
|
||||
@ -37,6 +38,27 @@ void QgsAdvancedDigitizingCanvasItem::paint( QPainter *painter )
|
||||
if ( !mAdvancedDigitizingDockWidget->cadEnabled() )
|
||||
return;
|
||||
|
||||
painter->setRenderHint( QPainter::Antialiasing );
|
||||
painter->setCompositionMode( QPainter::CompositionMode_Difference );
|
||||
|
||||
// Draw construction guides
|
||||
if ( mAdvancedDigitizingDockWidget->showConstructionGuides() )
|
||||
{
|
||||
if ( QgsVectorLayer *constructionGuidesLayer = mAdvancedDigitizingDockWidget->constructionGuidesLayer() )
|
||||
{
|
||||
QgsFeatureIterator it = constructionGuidesLayer->getFeatures( QgsFeatureRequest().setNoAttributes().setFilterRect( mMapCanvas->mapSettings().visibleExtent() ) );
|
||||
QgsFeature feature;
|
||||
painter->setPen( mConstructionGuidesPen );
|
||||
while ( it.nextFeature( feature ) )
|
||||
{
|
||||
QgsGeometry geom = feature.geometry();
|
||||
geom.mapToPixel( *mMapCanvas->getCoordinateTransform() );
|
||||
const QPolygonF polygon = geom.asQPolygonF();
|
||||
painter->drawPolyline( polygon );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use visible polygon rather than extent to properly handle rotated maps
|
||||
QPolygonF mapPoly = mMapCanvas->mapSettings().visiblePolygon();
|
||||
const double canvasWidth = QLineF( mapPoly[0], mapPoly[1] ).length();
|
||||
@ -83,9 +105,6 @@ void QgsAdvancedDigitizingCanvasItem::paint( QPainter *painter )
|
||||
snapSegmentPix2 = toCanvasCoordinates( snappedSegment[1] );
|
||||
}
|
||||
|
||||
painter->setRenderHint( QPainter::Antialiasing );
|
||||
painter->setCompositionMode( QPainter::CompositionMode_Difference );
|
||||
|
||||
// Draw point snap
|
||||
if ( curPointExist && snappedToVertex )
|
||||
{
|
||||
@ -226,7 +245,7 @@ void QgsAdvancedDigitizingCanvasItem::paint( QPainter *painter )
|
||||
}
|
||||
}
|
||||
|
||||
// Draw constr
|
||||
// Draw constraints
|
||||
if ( mAdvancedDigitizingDockWidget->betweenLineConstraint() == Qgis::BetweenLineConstraint::NoConstraint )
|
||||
{
|
||||
if ( curPointExist && previousPointExist )
|
||||
|
@ -60,6 +60,7 @@ class GUI_EXPORT QgsAdvancedDigitizingCanvasItem : public QgsMapCanvasItem
|
||||
QPen mSnapPen;
|
||||
QPen mSnapLinePen;
|
||||
QPen mCursorPen;
|
||||
QPen mConstructionGuidesPen;
|
||||
QgsAdvancedDigitizingDockWidget *mAdvancedDigitizingDockWidget = nullptr;
|
||||
};
|
||||
|
||||
|
@ -43,6 +43,9 @@
|
||||
|
||||
|
||||
const QgsSettingsEntryBool *QgsAdvancedDigitizingDockWidget::settingsCadSnappingPriorityPrioritizeFeature = new QgsSettingsEntryBool( QStringLiteral( "cad-snapping-prioritize-feature" ), QgsSettingsTree::sTreeDigitizing, false, tr( "Determines if snapping to features has priority over snapping to common angles." ) ) ;
|
||||
const QgsSettingsEntryBool *QgsAdvancedDigitizingDockWidget::settingsCadRecordConstructionGuides = new QgsSettingsEntryBool( QStringLiteral( "cad-record-construction-guides" ), QgsSettingsTree::sTreeDigitizing, false, tr( "Determines if construction guides are being recorded." ) ) ;
|
||||
const QgsSettingsEntryBool *QgsAdvancedDigitizingDockWidget::settingsCadShowConstructionGuides = new QgsSettingsEntryBool( QStringLiteral( "cad-show-construction-guides" ), QgsSettingsTree::sTreeDigitizing, true, tr( "Determines whether construction guides are shown." ) ) ;
|
||||
const QgsSettingsEntryBool *QgsAdvancedDigitizingDockWidget::settingsCadSnapToConstructionGuides = new QgsSettingsEntryBool( QStringLiteral( "cad-snap-to-construction-guides" ), QgsSettingsTree::sTreeDigitizing, false, tr( "Determines if points will snap to construction guides." ) ) ;
|
||||
|
||||
|
||||
QgsAdvancedDigitizingDockWidget::QgsAdvancedDigitizingDockWidget( QgsMapCanvas *canvas, QWidget *parent )
|
||||
@ -194,6 +197,46 @@ QgsAdvancedDigitizingDockWidget::QgsAdvancedDigitizingDockWidget( QgsMapCanvas *
|
||||
mCommonAngleActions.insert( it->first, action );
|
||||
}
|
||||
|
||||
// Construction modes
|
||||
QMenu *constructionSettingsMenu = new QMenu( this );
|
||||
|
||||
mRecordConstructionGuides = new QAction( tr( "Record Construction Guides" ), constructionSettingsMenu );
|
||||
mRecordConstructionGuides->setCheckable( true );
|
||||
mRecordConstructionGuides->setChecked( settingsCadRecordConstructionGuides->value() );
|
||||
constructionSettingsMenu->addAction( mRecordConstructionGuides );
|
||||
connect( mRecordConstructionGuides, &QAction::triggered, this, [ = ]() { settingsCadRecordConstructionGuides->setValue( mRecordConstructionGuides->isChecked() ); } );
|
||||
|
||||
mShowConstructionGuides = new QAction( tr( "Show Construction Guides" ), constructionSettingsMenu );
|
||||
mShowConstructionGuides->setCheckable( true );
|
||||
mShowConstructionGuides->setChecked( settingsCadShowConstructionGuides->value() );
|
||||
constructionSettingsMenu->addAction( mShowConstructionGuides );
|
||||
connect( mShowConstructionGuides, &QAction::triggered, this, [ = ]()
|
||||
{
|
||||
settingsCadShowConstructionGuides->setValue( mShowConstructionGuides->isChecked() );
|
||||
updateCadPaintItem();
|
||||
} );
|
||||
|
||||
mSnapToConstructionGuides = new QAction( tr( "Snap to Visible Construction Guides" ), constructionSettingsMenu );
|
||||
mSnapToConstructionGuides->setCheckable( true );
|
||||
mSnapToConstructionGuides->setChecked( settingsCadSnapToConstructionGuides->value() );
|
||||
constructionSettingsMenu->addAction( mSnapToConstructionGuides );
|
||||
connect( mSnapToConstructionGuides, &QAction::triggered, this, [ = ]() { settingsCadSnapToConstructionGuides->setValue( mSnapToConstructionGuides->isChecked() ); } );
|
||||
|
||||
constructionSettingsMenu->addSeparator();
|
||||
|
||||
mClearConstructionGuides = new QAction( tr( "Clear Construction Guides" ), constructionSettingsMenu );
|
||||
constructionSettingsMenu->addAction( mClearConstructionGuides );
|
||||
connect( mClearConstructionGuides, &QAction::triggered, this, [ = ]()
|
||||
{
|
||||
resetConstructionGuides();
|
||||
updateCadPaintItem();
|
||||
} );
|
||||
|
||||
QToolButton *constructionModeToolButton = qobject_cast< QToolButton *>( mToolbar->widgetForAction( mConstructionModeAction ) );
|
||||
constructionModeToolButton->setPopupMode( QToolButton::MenuButtonPopup );
|
||||
constructionModeToolButton->setMenu( constructionSettingsMenu );
|
||||
constructionModeToolButton->setObjectName( QStringLiteral( "ConstructionModeButton" ) );
|
||||
|
||||
qobject_cast< QToolButton *>( mToolbar->widgetForAction( mSettingsAction ) )->setPopupMode( QToolButton::InstantPopup );
|
||||
mSettingsAction->setMenu( mCommonAngleActionsMenu );
|
||||
mSettingsAction->setCheckable( true );
|
||||
@ -368,6 +411,12 @@ QgsAdvancedDigitizingDockWidget::QgsAdvancedDigitizingDockWidget( QgsMapCanvas *
|
||||
updateCapacity( true );
|
||||
connect( QgsProject::instance(), &QgsProject::snappingConfigChanged, this, [ = ] { updateCapacity( true ); } );
|
||||
|
||||
connect( QgsProject::instance(), &QgsProject::cleared, this, [ = ]()
|
||||
{
|
||||
mConstructionGuidesLayer.reset();
|
||||
} );
|
||||
connect( mMapCanvas, &QgsMapCanvas::destinationCrsChanged, this, [ = ] { updateConstructionGuidesCrs(); } );
|
||||
|
||||
disable();
|
||||
}
|
||||
|
||||
@ -672,6 +721,14 @@ void QgsAdvancedDigitizingDockWidget::setConstructionMode( bool enabled )
|
||||
{
|
||||
mConstructionMode = enabled;
|
||||
mConstructionModeAction->setChecked( enabled );
|
||||
|
||||
if ( recordConstructionGuides() )
|
||||
{
|
||||
if ( enabled && mCadPointList.size() > 1 )
|
||||
{
|
||||
mConstructionGuideLine.addVertex( mCadPointList.at( 1 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsAdvancedDigitizingDockWidget::settingsButtonTriggered( QAction *action )
|
||||
@ -1195,6 +1252,11 @@ bool QgsAdvancedDigitizingDockWidget::applyConstraints( QgsMapMouseEvent *e )
|
||||
context.setCadPoints( mCadPointList );
|
||||
context.setLockedSnapVertices( mLockedSnapVertices );
|
||||
|
||||
if ( snapToConstructionGuides() )
|
||||
{
|
||||
context.snappingUtils->addExtraSnapLayer( mConstructionGuidesLayer.get() );
|
||||
}
|
||||
|
||||
context.commonAngleConstraint.locked = !mMapCanvas->mapSettings().destinationCrs().isGeographic();
|
||||
context.commonAngleConstraint.relative = context.angleConstraint.relative;
|
||||
context.commonAngleConstraint.value = mCommonAngleConstraint;
|
||||
@ -1254,6 +1316,7 @@ bool QgsAdvancedDigitizingDockWidget::applyConstraints( QgsMapMouseEvent *e )
|
||||
* the point is not linked to a layer.
|
||||
*/
|
||||
e->setMapPoint( point );
|
||||
|
||||
mSnapMatch = context.snappingUtils->snapToMap( point, nullptr, true );
|
||||
if ( mSnapMatch.layer() )
|
||||
{
|
||||
@ -1265,6 +1328,8 @@ bool QgsAdvancedDigitizingDockWidget::applyConstraints( QgsMapMouseEvent *e )
|
||||
}
|
||||
}
|
||||
|
||||
context.snappingUtils->removeExtraSnapLayer( mConstructionGuidesLayer.get() );
|
||||
|
||||
if ( mSnapMatch.hasVertex() || mSnapMatch.hasLineEndpoint() )
|
||||
{
|
||||
toggleLockedSnapVertex( mSnapMatch, mLastSnapMatch );
|
||||
@ -1501,6 +1566,11 @@ bool QgsAdvancedDigitizingDockWidget::canvasKeyPressEventFilter( QKeyEvent *e )
|
||||
|
||||
void QgsAdvancedDigitizingDockWidget::clear()
|
||||
{
|
||||
if ( !mConstructionGuideLine.isEmpty() )
|
||||
{
|
||||
mConstructionGuideLine.clear();
|
||||
}
|
||||
|
||||
clearPoints();
|
||||
releaseLocks();
|
||||
}
|
||||
@ -1524,6 +1594,13 @@ void QgsAdvancedDigitizingDockWidget::keyPressEvent( QKeyEvent *e )
|
||||
case Qt::Key_Escape:
|
||||
{
|
||||
releaseLocks();
|
||||
|
||||
if ( mConstructionGuideLine.numPoints() >= 2 )
|
||||
{
|
||||
mConstructionGuidesLayer->dataProvider()->deleteFeatures( QgsFeatureIds() << mConstructionGuideId );
|
||||
mConstructionGuideLine.clear();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1575,6 +1652,22 @@ bool QgsAdvancedDigitizingDockWidget::filterKeyPress( QKeyEvent *e )
|
||||
const QEvent::Type type = e->type();
|
||||
switch ( e->key() )
|
||||
{
|
||||
case Qt::Key_Escape:
|
||||
{
|
||||
if ( mConstructionMode && mConstructionGuideLine.numPoints() >= 2 )
|
||||
{
|
||||
mConstructionGuidesLayer->dataProvider()->deleteFeatures( QgsFeatureIds() << mConstructionGuideId );
|
||||
mConstructionGuideLine.clear();
|
||||
|
||||
if ( mCadPointList.size() > 1 )
|
||||
{
|
||||
mConstructionGuideLine.addVertex( mCadPointList.at( 1 ) );
|
||||
}
|
||||
|
||||
updateCadPaintItem();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Qt::Key_X:
|
||||
{
|
||||
// modifier+x ONLY caught for ShortcutOverride events...
|
||||
@ -1856,7 +1949,20 @@ void QgsAdvancedDigitizingDockWidget::enable()
|
||||
{
|
||||
show();
|
||||
}
|
||||
|
||||
setCadEnabled( mSessionActive );
|
||||
|
||||
if ( !mConstructionGuidesLayer )
|
||||
{
|
||||
resetConstructionGuides();
|
||||
}
|
||||
|
||||
if ( mDeferredUpdateConstructionGuidesCrs )
|
||||
{
|
||||
updateConstructionGuidesCrs();
|
||||
}
|
||||
|
||||
updateCadPaintItem();
|
||||
}
|
||||
|
||||
void QgsAdvancedDigitizingDockWidget::disable()
|
||||
@ -1903,6 +2009,39 @@ void QgsAdvancedDigitizingDockWidget::addPoint( const QgsPointXY &point )
|
||||
mCadPointList.insert( 0, pt );
|
||||
}
|
||||
|
||||
if ( recordConstructionGuides() )
|
||||
{
|
||||
if ( constructionMode() )
|
||||
{
|
||||
mConstructionGuideLine.addVertex( pt );
|
||||
|
||||
if ( mConstructionGuideLine.numPoints() == 2 )
|
||||
{
|
||||
QgsFeature feature;
|
||||
QgsGeometry geom( mConstructionGuideLine.clone() );
|
||||
feature.setGeometry( geom );
|
||||
mConstructionGuidesLayer->dataProvider()->addFeature( feature );
|
||||
mConstructionGuideId = feature.id();
|
||||
}
|
||||
else if ( mConstructionGuideLine.numPoints() > 2 )
|
||||
{
|
||||
QgsGeometry geom( mConstructionGuideLine.clone() );
|
||||
mConstructionGuidesLayer->dataProvider()->changeGeometryValues( { { mConstructionGuideId, geom } } );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !mConstructionGuideLine.isEmpty() )
|
||||
{
|
||||
mConstructionGuideLine.addVertex( pt );
|
||||
|
||||
QgsGeometry geom( mConstructionGuideLine.clone() );
|
||||
mConstructionGuidesLayer->dataProvider()->changeGeometryValues( { { mConstructionGuideId, geom } } );
|
||||
mConstructionGuideLine.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateCapacity();
|
||||
updateCadPaintItem();
|
||||
}
|
||||
@ -2146,3 +2285,58 @@ double QgsAdvancedDigitizingDockWidget::getLineM( ) const
|
||||
{
|
||||
return mMLineEdit->isEnabled() ? QLocale().toDouble( mMLineEdit->text() ) : std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
|
||||
bool QgsAdvancedDigitizingDockWidget::showConstructionGuides() const
|
||||
{
|
||||
return mShowConstructionGuides ? mShowConstructionGuides->isChecked() : false;
|
||||
}
|
||||
|
||||
bool QgsAdvancedDigitizingDockWidget::snapToConstructionGuides() const
|
||||
{
|
||||
return mSnapToConstructionGuides ? mShowConstructionGuides->isChecked() && mSnapToConstructionGuides->isChecked() : false;
|
||||
}
|
||||
|
||||
bool QgsAdvancedDigitizingDockWidget::recordConstructionGuides() const
|
||||
{
|
||||
return mRecordConstructionGuides ? mRecordConstructionGuides->isChecked() : false;
|
||||
}
|
||||
|
||||
void QgsAdvancedDigitizingDockWidget::updateConstructionGuidesCrs()
|
||||
{
|
||||
if ( !mConstructionGuidesLayer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !cadEnabled() )
|
||||
{
|
||||
mDeferredUpdateConstructionGuidesCrs = true;
|
||||
}
|
||||
|
||||
QgsCoordinateTransform transform = QgsCoordinateTransform( mConstructionGuidesLayer->crs(), mMapCanvas->mapSettings().destinationCrs(), QgsProject::instance()->transformContext() );
|
||||
mConstructionGuidesLayer->setCrs( mMapCanvas->mapSettings().destinationCrs() );
|
||||
QgsFeatureIterator it = mConstructionGuidesLayer->getFeatures( QgsFeatureRequest().setNoAttributes() );
|
||||
QgsFeature feature;
|
||||
while ( it.nextFeature( feature ) )
|
||||
{
|
||||
QgsGeometry geom = feature.geometry();
|
||||
geom.transform( transform );
|
||||
mConstructionGuidesLayer->dataProvider()->changeGeometryValues( { { feature.id(), geom } } );
|
||||
}
|
||||
|
||||
mDeferredUpdateConstructionGuidesCrs = false;
|
||||
}
|
||||
|
||||
void QgsAdvancedDigitizingDockWidget::resetConstructionGuides()
|
||||
{
|
||||
if ( mConstructionGuidesLayer )
|
||||
{
|
||||
mConstructionGuidesLayer.reset();
|
||||
}
|
||||
|
||||
const QgsVectorLayer::LayerOptions options( QgsProject::instance()->transformContext(), false, false );
|
||||
mConstructionGuidesLayer = std::make_unique<QgsVectorLayer>( QStringLiteral( "LineString?crs=%1" ).arg( mMapCanvas->mapSettings().destinationCrs().authid() ),
|
||||
QStringLiteral( "constructionGuides" ),
|
||||
QStringLiteral( "memory" ),
|
||||
options );
|
||||
}
|
||||
|
@ -305,9 +305,36 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QgsDockWidget, private
|
||||
*/
|
||||
void setEnabledM( bool enable );
|
||||
|
||||
//! construction mode is used to draw intermediate points. These points won't be given any further (i.e. to the map tools)
|
||||
/**
|
||||
* Returns whether the construction mode is activated. The construction mode is used to draw intermediate
|
||||
* points that will not be part of a geometry being digitized.
|
||||
*/
|
||||
bool constructionMode() const { return mConstructionMode; }
|
||||
|
||||
/**
|
||||
* Returns the vector layer within which construction guides are stored.
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
QgsVectorLayer *constructionGuidesLayer() const { return mConstructionGuidesLayer.get(); }
|
||||
|
||||
/**
|
||||
* Returns whether the construction guides are visible.
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
bool showConstructionGuides() const;
|
||||
|
||||
/**
|
||||
* Returns whether points should snap to construction guides.
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
bool snapToConstructionGuides() const;
|
||||
|
||||
/**
|
||||
* Returns whether construction guides are being recorded.
|
||||
* \since QGIS 3.40
|
||||
*/
|
||||
bool recordConstructionGuides() const;
|
||||
|
||||
/**
|
||||
* Returns the between line constraints which are used to place
|
||||
* perpendicular/parallel segments to snapped segments on the canvas
|
||||
@ -1013,7 +1040,6 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QgsDockWidget, private
|
||||
//! Updates values of constraints that are not locked based on the current point
|
||||
void updateUnlockedConstraintValues( const QgsPoint &point );
|
||||
|
||||
|
||||
/**
|
||||
* Adds or removes the snap match if it is already in the locked snap queue or not.
|
||||
* \param snapMatch the snap match to add or remove.
|
||||
@ -1021,6 +1047,17 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QgsDockWidget, private
|
||||
*/
|
||||
void toggleLockedSnapVertex( const QgsPointLocator::Match &snapMatch, QgsPointLocator::Match previouslySnap );
|
||||
|
||||
/**
|
||||
* Resets the vector layer and point locator objects handling construction guides.
|
||||
*/
|
||||
void resetConstructionGuides();
|
||||
|
||||
/**
|
||||
* Updates the construction guides layer CRS to match the map canvas' destination CRS
|
||||
* and reproject pre-existing construction guides.
|
||||
*/
|
||||
void updateConstructionGuidesCrs();
|
||||
|
||||
QgsMapCanvas *mMapCanvas = nullptr;
|
||||
QgsAdvancedDigitizingCanvasItem *mCadPaintItem = nullptr;
|
||||
//! Snapping indicator
|
||||
@ -1053,19 +1090,29 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QgsDockWidget, private
|
||||
//! Flag that controls whether snapping to features has priority over common angle
|
||||
bool mSnappingPrioritizeFeatures = false;
|
||||
|
||||
// point list and current snap point / segment
|
||||
// Point list and current snap point / segment
|
||||
QList<QgsPoint> mCadPointList;
|
||||
QList<QgsPointXY> mSnappedSegment;
|
||||
|
||||
bool mSessionActive = false;
|
||||
|
||||
// error message
|
||||
// Construction path history
|
||||
std::unique_ptr<QgsVectorLayer> mConstructionGuidesLayer;
|
||||
QgsFeatureId mConstructionGuideId;
|
||||
QgsLineString mConstructionGuideLine;
|
||||
bool mDeferredUpdateConstructionGuidesCrs = false;
|
||||
|
||||
// Error message
|
||||
std::unique_ptr<QgsMessageBarItem> mErrorMessage;
|
||||
|
||||
// UI
|
||||
QMap< double, QAction *> mCommonAngleActions; // map the common angle actions with their angle values
|
||||
QAction *mLineExtensionAction;
|
||||
QAction *mXyVertexAction;
|
||||
QAction *mLineExtensionAction = nullptr;
|
||||
QAction *mXyVertexAction = nullptr;
|
||||
QAction *mRecordConstructionGuides = nullptr;
|
||||
QAction *mShowConstructionGuides = nullptr;
|
||||
QAction *mSnapToConstructionGuides = nullptr;
|
||||
QAction *mClearConstructionGuides = nullptr;
|
||||
|
||||
// Snap indicator
|
||||
QgsPointLocator::Match mSnapMatch;
|
||||
@ -1088,6 +1135,9 @@ class GUI_EXPORT QgsAdvancedDigitizingDockWidget : public QgsDockWidget, private
|
||||
QMenu *mFloaterActionsMenu = nullptr;
|
||||
|
||||
static const QgsSettingsEntryBool *settingsCadSnappingPriorityPrioritizeFeature;
|
||||
static const QgsSettingsEntryBool *settingsCadRecordConstructionGuides;
|
||||
static const QgsSettingsEntryBool *settingsCadShowConstructionGuides;
|
||||
static const QgsSettingsEntryBool *settingsCadSnapToConstructionGuides;
|
||||
|
||||
friend class TestQgsAdvancedDigitizing;
|
||||
friend class TestQgsAdvancedDigitizingDockWidget;
|
||||
|
@ -60,6 +60,8 @@ class TestQgsAdvancedDigitizing: public QObject
|
||||
|
||||
void releaseLockAfterDisable();
|
||||
|
||||
void constructionGuides();
|
||||
|
||||
private:
|
||||
TestQgsMapToolAdvancedDigitizingUtils getMapToolDigitizingUtils( QgsVectorLayer *layer );
|
||||
QString getWktFromLastAddedFeature( TestQgsMapToolAdvancedDigitizingUtils utils, QSet<QgsFeatureId> oldFeatures );
|
||||
@ -1163,5 +1165,55 @@ void TestQgsAdvancedDigitizing::releaseLockAfterDisable()
|
||||
mAdvancedDigitizingDockWidget->enableAction()->trigger();
|
||||
}
|
||||
|
||||
void TestQgsAdvancedDigitizing::constructionGuides()
|
||||
{
|
||||
auto utils = getMapToolDigitizingUtils( mLayer3950 );
|
||||
|
||||
QVERIFY( mAdvancedDigitizingDockWidget->cadEnabled() );
|
||||
|
||||
QCOMPARE( mAdvancedDigitizingDockWidget->constructionGuidesLayer()->featureCount(), 0 );
|
||||
|
||||
mAdvancedDigitizingDockWidget->mRecordConstructionGuides->setChecked( true );
|
||||
mAdvancedDigitizingDockWidget->setConstructionMode( true );
|
||||
|
||||
// enter a few construction steps while guide recording is on
|
||||
utils.mouseClick( 10, 10, Qt::LeftButton );
|
||||
utils.mouseClick( 10, 11, Qt::LeftButton );
|
||||
utils.mouseClick( 10, 12, Qt::LeftButton );
|
||||
utils.mouseClick( 10, 13, Qt::LeftButton );
|
||||
utils.mouseClick( 10, 14, Qt::LeftButton );
|
||||
utils.mouseClick( 20, 01, Qt::RightButton );
|
||||
|
||||
QCOMPARE( mAdvancedDigitizingDockWidget->constructionGuidesLayer()->featureCount(), 1 );
|
||||
|
||||
mAdvancedDigitizingDockWidget->mRecordConstructionGuides->setChecked( false );
|
||||
|
||||
// enter a few construction steps while guide recording is off
|
||||
utils.mouseClick( 10, 10, Qt::LeftButton );
|
||||
utils.mouseClick( 10, 11, Qt::LeftButton );
|
||||
utils.mouseClick( 10, 12, Qt::LeftButton );
|
||||
utils.mouseClick( 10, 13, Qt::LeftButton );
|
||||
utils.mouseClick( 10, 14, Qt::LeftButton );
|
||||
utils.mouseClick( 20, 01, Qt::RightButton );
|
||||
|
||||
QCOMPARE( mAdvancedDigitizingDockWidget->constructionGuidesLayer()->featureCount(), 1 );
|
||||
|
||||
QgsSnappingConfig snapConfig = mCanvas->snappingUtils()->config();
|
||||
snapConfig.setEnabled( true );
|
||||
mCanvas->snappingUtils()->setConfig( snapConfig );
|
||||
|
||||
mAdvancedDigitizingDockWidget->mSnapToConstructionGuides->setChecked( true );
|
||||
|
||||
// snap on an existing constructio guide vertex
|
||||
utils.mouseMove( 10.1, 10 );
|
||||
QCOMPARE( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 10, 10 ) );
|
||||
|
||||
mAdvancedDigitizingDockWidget->mSnapToConstructionGuides->setChecked( false );
|
||||
|
||||
// do not snap on an existing construction guide vertex
|
||||
utils.mouseMove( 10.5, 14.5 );
|
||||
QGSCOMPARENEARPOINT( mAdvancedDigitizingDockWidget->currentPointV2(), QgsPoint( 10.5, 14.5 ), 0.1 );
|
||||
}
|
||||
|
||||
QGSTEST_MAIN( TestQgsAdvancedDigitizing )
|
||||
#include "testqgsadvanceddigitizing.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user