38#include "moc_qgsmaptooleditblanksegments.cpp"
60 QgsSymbolLayerFinder(
const QString &symbolLayerId )
61 : mSymbolLayerId( symbolLayerId )
75 bool visitSymbol(
const QgsSymbol *symbol )
77 if ( symbol && !mSymbol )
83 if ( sl->
id() == mSymbolLayerId )
86 mSymbolLayerIndex = mSymbolLayer ? idx : -1;
91 if (
const QgsSymbol *subSymbol =
const_cast<QgsSymbolLayer *
>( sl )->subSymbol(); subSymbol && !visitSymbol( subSymbol ) )
105 if ( symbolEntity->symbol() )
106 visitSymbol( symbolEntity->symbol() );
114 const QgsSymbol *symbol()
const {
return mSymbol; }
124 int symbolLayerIndex()
const {
return mSymbolLayerIndex; }
129 int mSymbolLayerIndex = -1;
130 const QString &mSymbolLayerId;
137 const QPointF &pointAt(
const QList<QList<QPolygonF>> &points,
int partIndex,
int ringIndex,
int pointIndex )
139 if ( partIndex < 0 || partIndex >= points.count() )
140 throw std::invalid_argument(
"Blank segments internal error : Invalid part index" );
142 const QList<QPolygonF> &rings = points.at( partIndex );
143 if ( ringIndex < 0 || ringIndex >= rings.count() )
144 throw std::invalid_argument(
"blank segments internal error : Invalid ring index" );
146 const QPolygonF &pts = rings.at( ringIndex );
147 if ( pointIndex < 0 || pointIndex >= pts.count() )
148 throw std::invalid_argument(
"blank segments internal error : Invalid point index" );
150 return pts.at( pointIndex );
153 enum ProjectedPointStatus
164 QPointF projectedPoint(
const QPointF &lineStartPt,
const QPointF &lineEndPt,
const QPointF &point,
double &distance, ProjectedPointStatus &status )
166 status = ProjectedPointStatus::OK;
169 const double Ax = lineStartPt.x();
170 const double Ay = lineStartPt.y();
171 const double Bx = lineEndPt.x();
172 const double By = lineEndPt.y();
173 const double Cx = point.x();
174 const double Cy = point.y();
179 status = ProjectedPointStatus::LINE_EMPTY;
183 const double r = ( ( Cx - Ax ) * ( Bx - Ax ) + ( Cy - Ay ) * ( By - Ay ) ) / std::pow( length, 2 );
184 if ( r < 0 or r > 1 )
186 status = ProjectedPointStatus::NOT_ON_SEGMENT;
190 const double Px = Ax + r * ( Bx - Ax );
191 const double Py = Ay + r * ( By - Ay );
195 return QPointF( Px, Py );
238 void setPoints(
int partIndex,
int ringIndex,
int startIndex,
int endIndex, QPointF startPt, QPointF endPt );
293 const QPointF &
pointAt(
int index )
const;
303 int mStartIndex = -1;
307 bool mNeedSwap =
false;
314 , mSymbolLayer( symbolLayer )
315 , mPropertyButton( propertyButton )
326 initRubberBand( mStartRubberBand );
327 initRubberBand( mEndRubberBand );
329 mEditedBlankSegment->setHighlighted(
true );
335 mState = SelectFeature;
344 if ( !mLayer || !mLayer->renderer() || !mSymbolLayer )
347 if ( !mSymbol || !mRenderedPointsSymbolLayer )
350 QgsSymbolLayerFinder
finder( mSymbolLayer->id() );
351 mLayer->renderer()->accept( &
finder );
354 mSymbol.reset(
finder.symbol()->clone() );
355 if ( mRenderedPointsSymbolLayer = createRenderedPointsSymbolLayer(
finder.symbolLayer() ); mRenderedPointsSymbolLayer )
358 mSymbol->changeSymbolLayer(
finder.symbolLayerIndex(), mRenderedPointsSymbolLayer );
363 QgsDebugError(
"Fail to create fake templated line symbol layer" );
368 QgsDebugError(
"Fail to retrieve symbol and templated line symbol layer" );
377 if ( !mSymbol ||
mPoints.isEmpty() )
380 const QPoint &pos = e->pos();
382 if (
canvas()->extent() != mExtent )
389 case State::SelectFeature:
390 case State::BlankSegmentSelected:
391 case State::FeatureSelected:
394 case State::BlankSegmentCreationStarted:
395 mState = State::FeatureSelected;
396 setCurrentBlankSegment( -1 );
399 case State::BlankSegmentModificationStarted:
400 mState = State::BlankSegmentSelected;
402 setCurrentBlankSegment( mCurrentBlankSegmentIndex );
409 case State::SelectFeature:
412 case State::BlankSegmentSelected:
413 updateHoveredBlankSegment( pos );
416 case State::FeatureSelected:
418 updateHoveredBlankSegment( pos );
421 mStartRubberBand->setVisible( mHoveredBlankSegmentIndex == -1 );
422 if ( mHoveredBlankSegmentIndex == -1 )
427 int partIndex = -1, ringIndex = -1, pointIndex = -1;
428 const QPointF closestPt = closestPoint( pos, distance, partIndex, ringIndex, pointIndex );
431 mStartRubberBand->addPoint( m2p.
toMapCoordinates( closestPt.x(), closestPt.y() ) );
437 case State::BlankSegmentModificationStarted:
438 case State::BlankSegmentCreationStarted:
440 double distance = -1;
444 QPointF P = closestPoint( pos, distance, partIndex, ringIndex, pointIndex );
445 if ( distance > -1 && pointIndex > -1 )
447 mEditedBlankSegment->setPoints( partIndex, ringIndex, mEditedBlankSegment->getStartIndex(), pointIndex, mEditedBlankSegment->getStartPoint(), P );
448 updateStartEndRubberBand();
455void QgsMapToolEditBlankSegmentsBase::selectFeature(
QgsMapMouseEvent *event )
465 messageEmitted( tr(
"No feature was detected at the clicked position. Please click closer to the feature or enhance the search tolerance under Settings->Options->Digitizing->Search radius for vertex edits" ),
Qgis::MessageLevel::Critical );
470 if ( mBlankSegmentsFieldIndex < 0 )
476 if ( mBlankSegmentsFieldIndex < 0 )
478 if ( !mLayer->auxiliaryLayer() )
480 QgsNewAuxiliaryLayerDialog dlg( mLayer );
484 if ( !mLayer->auxiliaryLayer() )
488 if ( mBlankSegmentsFieldIndex < 0 )
490 emit
messageEmitted( tr(
"Failed to create blank segments auxiliary field for layer '%1'" ).arg( mLayer->name() ) );
495 QgsPropertyCollection
c = mSymbolLayer->dataDefinedProperties();
497 mPropertyButton->updateFieldLists();
498 mPropertyButton->setToProperty( property );
499 emit mPropertyButton->changed();
504 const bool usesAuxFields = mLayer->fields().fieldOrigin( mBlankSegmentsFieldIndex ) ==
Qgis::FieldOrigin::Join;
505 if ( !usesAuxFields && !mLayer->isEditable() )
507 if ( mLayer->startEditing() )
509 emit
messageEmitted( tr(
"Layer “%1” was made editable" ).arg( mLayer->name() ) );
513 emit
messageEmitted( tr(
"Cannot modify blank segments — the layer “%1” could not be made editable" ).arg( mLayer->name() ) );
520 updateHoveredBlankSegment( event->pos() );
522 mState = State::FeatureSelected;
529 case State::SelectFeature:
534 case State::FeatureSelected:
537 if ( mHoveredBlankSegmentIndex > -1 )
539 mState = State::BlankSegmentSelected;
540 setCurrentBlankSegment( mHoveredBlankSegmentIndex );
545 mState = State::BlankSegmentCreationStarted;
546 double distance = -1;
550 QPointF P = closestPoint( e->pos(), distance, partIndex, ringIndex, pointIndex );
551 if ( distance > -1 && pointIndex > -1 )
553 mEditedBlankSegment->setPoints( partIndex, ringIndex, pointIndex, pointIndex, P, P );
554 updateStartEndRubberBand();
560 case State::BlankSegmentSelected:
562 Q_ASSERT( mCurrentBlankSegmentIndex > -1 && mCurrentBlankSegmentIndex <
static_cast<int>( mBlankSegments.size() ) );
566 if ( mHoveredBlankSegmentIndex > -1 && mHoveredBlankSegmentIndex != mCurrentBlankSegmentIndex )
568 setCurrentBlankSegment( mHoveredBlankSegmentIndex );
572 const double distanceFromStart = ( currentBlankSegment->getStartPoint() - e->pos() ).manhattanLength();
573 const double distanceFromEnd = ( currentBlankSegment->getEndPoint() - e->pos() ).manhattanLength();
576 if ( std::min( distanceFromStart, distanceFromEnd ) <
TOLERANCE )
578 if ( distanceFromStart < distanceFromEnd )
581 mEditedBlankSegment->setPoints(
582 currentBlankSegment->getPartIndex(),
583 currentBlankSegment->getRingIndex(),
584 currentBlankSegment->getEndIndex(),
585 currentBlankSegment->getStartIndex(),
586 currentBlankSegment->getEndPoint(),
587 currentBlankSegment->getStartPoint()
591 mState = State::BlankSegmentModificationStarted;
598 case State::BlankSegmentModificationStarted:
599 case State::BlankSegmentCreationStarted:
602 if ( mCurrentBlankSegmentIndex < 0 )
605 mBlankSegments.back()->copyFrom( *mEditedBlankSegment );
606 mState = State::FeatureSelected;
612 blankSegment->copyFrom( *mEditedBlankSegment );
613 mState = State::BlankSegmentSelected;
628 case State::SelectFeature:
631 case State::BlankSegmentSelected:
632 if ( e->matches( QKeySequence::Delete ) && mCurrentBlankSegmentIndex > -1 )
634 mState = State::FeatureSelected;
635 int toRemoveIndex = mCurrentBlankSegmentIndex;
636 setCurrentBlankSegment( -1 );
637 mBlankSegments.erase( mBlankSegments.begin() + toRemoveIndex );
641 else if ( e->matches( QKeySequence::Cancel ) )
643 mState = State::FeatureSelected;
644 setCurrentBlankSegment( -1 );
650 case State::FeatureSelected:
651 if ( e->matches( QKeySequence::Cancel ) )
654 mState = State::SelectFeature;
660 case State::BlankSegmentCreationStarted:
661 if ( e->matches( QKeySequence::Cancel ) )
663 mState = State::FeatureSelected;
664 setCurrentBlankSegment( -1 );
669 case State::BlankSegmentModificationStarted:
670 if ( e->matches( QKeySequence::Cancel ) )
672 mState = State::BlankSegmentSelected;
674 setCurrentBlankSegment( mCurrentBlankSegmentIndex );
683 double startDistance = 0;
684 const int startIndex = mNeedSwap ? mEndIndex : mStartIndex;
685 const QPointF startPt = mNeedSwap ? mEndPt : mStartPt;
686 for (
int i = 1; i < startIndex; i++ )
693 double endDistance = startDistance;
704 return QPair<double, double>( startDistance, endDistance );
707int QgsMapToolEditBlankSegmentsBase::closestBlankSegmentIndex(
const QPointF &point,
double &distance )
const
711 int iBlankSegment = -1;
712 for (
int i = 0; i < static_cast<int>( mBlankSegments.size() ); i++ )
715 for (
int iPoint = 1; iPoint < blankSegment->pointsCount(); iPoint++ )
718 ProjectedPointStatus status = ProjectedPointStatus::OK;
722 projectedPoint( blankSegment->pointAt( iPoint - 1 ), blankSegment->pointAt( iPoint ), point, d, status );
724 catch ( std::invalid_argument &e )
732 case ProjectedPointStatus::LINE_EMPTY:
735 case ProjectedPointStatus::NOT_ON_SEGMENT:
736 d = std::min( ( blankSegment->getStartPoint() - point ).manhattanLength(), ( blankSegment->getEndPoint() - point ).manhattanLength() );
739 case ProjectedPointStatus::OK:
743 if ( distance == -1 || d < distance )
751 return iBlankSegment;
754QPointF QgsMapToolEditBlankSegmentsBase::closestPoint(
const QPointF &point,
double &distance,
int &partIndex,
int &ringIndex,
int &pointIndex )
const
757 QPointF currentPoint;
760 for (
int iPart = 0; iPart <
mPoints.count(); iPart++ )
762 const QList<QPolygonF> &rings =
mPoints.at( iPart );
763 for (
int iRing = 0; iRing < rings.count(); iRing++ )
765 const QPolygonF &points = rings.at( iRing );
766 for (
int i = 1; i < points.count(); i++ )
769 ProjectedPointStatus status = ProjectedPointStatus::OK;
770 QPointF P = projectedPoint( points.at( i - 1 ), points.at( i ), point, d, status );
773 case ProjectedPointStatus::LINE_EMPTY:
774 case ProjectedPointStatus::NOT_ON_SEGMENT:
777 case ProjectedPointStatus::OK:
781 if ( distance == -1 || d < distance )
796void QgsMapToolEditBlankSegmentsBase::updateStartEndRubberBand()
801 bool displayEndPoint =
true;
804 case State::SelectFeature:
805 case State::BlankSegmentCreationStarted:
808 case State::FeatureSelected:
809 displayEndPoint =
false;
812 case State::BlankSegmentSelected:
813 case State::BlankSegmentModificationStarted:
819 const QPointF &startPoint = mEditedBlankSegment->getStartPoint();
820 mStartRubberBand->addPoint( m2p.
toMapCoordinates( startPoint.x(), startPoint.y() ) );
822 if ( displayEndPoint )
824 const QPointF &endPoint = mEditedBlankSegment->getEndPoint();
825 mEndRubberBand->addPoint( m2p.
toMapCoordinates( endPoint.x(), endPoint.y() ) );
829void QgsMapToolEditBlankSegmentsBase::updateHoveredBlankSegment(
const QPoint &pos )
831 double distance = -1;
832 int iBlankSegment = closestBlankSegmentIndex( pos, distance );
834 if ( mHoveredBlankSegmentIndex > -1 && mHoveredBlankSegmentIndex <
static_cast<int>( mBlankSegments.size() ) && mHoveredBlankSegmentIndex != mCurrentBlankSegmentIndex )
836 mBlankSegments.at( mHoveredBlankSegmentIndex )->setHighlighted(
false );
840 if ( iBlankSegment > -1 && distance <
TOLERANCE )
842 mHoveredBlankSegmentIndex = iBlankSegment;
843 if ( mHoveredBlankSegmentIndex <
static_cast<int>( mBlankSegments.size() ) )
845 mBlankSegments.at( mHoveredBlankSegmentIndex )->setHighlighted(
true );
851 mHoveredBlankSegmentIndex = -1;
855void QgsMapToolEditBlankSegmentsBase::setCurrentBlankSegment(
int currentBlankSegmentIndex )
859 if ( mCurrentBlankSegmentIndex > -1 && mCurrentBlankSegmentIndex <
static_cast<int>( mBlankSegments.size() ) )
861 mBlankSegments.at( mCurrentBlankSegmentIndex )->setVisible(
true );
862 mBlankSegments.at( mCurrentBlankSegmentIndex )->setHighlighted(
false );
865 mCurrentBlankSegmentIndex = currentBlankSegmentIndex;
866 if ( mCurrentBlankSegmentIndex > -1 && mCurrentBlankSegmentIndex <
static_cast<int>( mBlankSegments.size() ) )
868 mBlankSegments.at( mCurrentBlankSegmentIndex )->setVisible(
false );
869 mEditedBlankSegment->copyFrom( *( mBlankSegments.at( mCurrentBlankSegmentIndex ).get() ) );
873 mEditedBlankSegment->setVisible(
false );
876 updateStartEndRubberBand();
879void QgsMapToolEditBlankSegmentsBase::updateAttribute()
881 if ( !mRenderedPointsSymbolLayer )
884 QList<QList<QgsSymbolLayerUtils::BlankSegments>> blankSegments;
885 for (
const QObjectUniquePtr<QgsBlankSegmentRubberBand> &blankSegment : mBlankSegments )
889 QPair<double, double> startEndDistance = blankSegment->getStartEndDistance( mRenderedPointsSymbolLayer->blankSegmentsUnit() );
891 const int partIndex = blankSegment->getPartIndex();
892 if ( partIndex >= blankSegments.count() )
893 blankSegments.resize( partIndex + 1 );
895 QList<QgsSymbolLayerUtils::BlankSegments> &rings = blankSegments[partIndex];
896 const int ringIndex = blankSegment->getRingIndex();
897 if ( ringIndex >= rings.count() )
898 rings.resize( ringIndex + 1 );
900 QgsSymbolLayerUtils::BlankSegments &segments = rings[ringIndex];
901 segments << startEndDistance;
903 catch ( std::invalid_argument &e )
910 QStringList strParts;
911 for ( QList<QgsSymbolLayerUtils::BlankSegments> &part : blankSegments )
913 QStringList strRings;
914 for ( QgsSymbolLayerUtils::BlankSegments &ring : part )
916 std::sort( ring.begin(), ring.end() );
917 QStringList strDistances;
918 for (
const QPair<double, double> &distance : ring )
920 strDistances << ( QString::number( distance.first ) +
" " + QString::number( distance.second ) );
923 strRings <<
"(" + strDistances.join(
"," ) +
")";
926 strParts <<
"(" + strRings.join(
"," ) +
")";
929 QString strNewBlankSegments =
"(" + strParts.join(
"," ) +
")";
931 mLayer->beginEditCommand( tr(
"Set blank segment list" ) );
932 if ( mLayer->changeAttributeValue( mCurrentFeatureId, mBlankSegmentsFieldIndex, strNewBlankSegments ) )
934 mLayer->endEditCommand();
935 mLayer->triggerRepaint();
940 mLayer->destroyEditCommand();
944void QgsMapToolEditBlankSegmentsBase::loadFeaturePoints()
948 mBlankSegments.clear();
949 setCurrentBlankSegment( -1 );
951 if (
FID_IS_NULL( mCurrentFeatureId ) || !mRenderedPointsSymbolLayer )
955 feature = mLayer->getFeature( mCurrentFeatureId );
956 QString currentBlankSegments = feature.
attribute( mBlankSegmentsFieldIndex ).toString();
961 QgsCoordinateTransform transform(
canvas()->mapSettings().layerTransform( mLayer ) );
962 QgsNullPaintDevice nullPaintDevice;
963 QPainter painter( &nullPaintDevice );
966 mSymbol->startRender( context );
967 mSymbol->renderFeature( feature, context );
968 mSymbol->stopRender( context );
974 QList<QList<QgsSymbolLayerUtils::BlankSegments>> allBlankSegments = QgsSymbolLayerUtils::parseBlankSegments( currentBlankSegments, context, mRenderedPointsSymbolLayer->blankSegmentsUnit(), error );
975 if ( !error.isEmpty() )
982 for (
int iPart = 0; iPart <
mPoints.count(); iPart++ )
984 const QList<QPolygonF> &rings =
mPoints.at( iPart );
985 for (
int iRing = 0; iRing < rings.count(); iRing++ )
987 if ( iPart >= allBlankSegments.count() || iRing >= allBlankSegments.at( iPart ).count() )
990 const QgsSymbolLayerUtils::BlankSegments &blankSegments = allBlankSegments.at( iPart ).at( iRing );
992 double currentLength = 0;
994 const QPolygonF &points = rings.at( iRing );
995 for ( QPair<double, double> ba : blankSegments )
997 while ( iPoint < points.count() - 1 && currentLength < ba.first )
1003 if ( iPoint == points.count() )
1006 int startIndex = iPoint;
1007 Line l( points.at( iPoint ), points.at( iPoint - 1 ) );
1008 QPointF startPt = points.at( iPoint ) + l.diffForInterval( currentLength - ba.first );
1010 while ( iPoint < points.count() - 1 && currentLength < ba.second )
1016 if ( iPoint == points.count() )
1019 int endIndex = iPoint;
1020 Line l2( points.at( iPoint ), points.at( iPoint - 1 ) );
1021 QPointF endPt = points.at( iPoint ) + l2.diffForInterval( currentLength - ba.second );
1042 setPoints( partIndex, ringIndex, startIndex, endIndex, startPt, endPt );
1047 mPartIndex = partIndex;
1048 mRingIndex = ringIndex;
1049 mStartIndex = startIndex;
1050 mEndIndex = endIndex;
1055 if ( mStartIndex == mEndIndex )
1059 if (
const QPointF &startIndexPoint =
::pointAt( mPoints, mPartIndex, mRingIndex, mStartIndex );
1065 catch ( std::invalid_argument &e )
1070 else if ( mStartIndex > mEndIndex )
1078void QgsMapToolEditBlankSegmentsBase::QgsBlankSegmentRubberBand::updatePoints()
1080 const QgsMapToPixel &m2p = *( mMapCanvas->getCoordinateTransform() );
1083 for (
int iPoint = 0; iPoint < pointsCount(); iPoint++ )
1087 const QPointF &point = pointAt( iPoint );
1089 addPoint( mapPoint, iPoint == pointsCount() - 1 );
1091 catch ( std::invalid_argument &e )
1143 return std::abs( mEndIndex - mStartIndex ) + 2;
1150 ( mNeedSwap ? mEndPt : mStartPt )
1152 : ( index ==
pointsCount() - 1 ? ( mNeedSwap ? mStartPt : mEndPt )
1154 :
::pointAt( mPoints, mPartIndex, mRingIndex, ( mNeedSwap ? mEndIndex : mStartIndex ) + index - 1 ) );
Keeps a pointer to a QObject and deletes it whenever this object is deleted.
Provides global constants and enumerations for use throughout the application.
@ Critical
Critical/error message.
@ Join
Field originates from a joined layer.
RenderUnit
Rendering size units.
static int createProperty(QgsPalLayerSettings::Property property, QgsVectorLayer *vlayer, bool overwriteExisting=true)
Creates if necessary a new auxiliary field for a PAL property and activates this property in settings...
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
static double distance2D(double x1, double y1, double x2, double y2)
Returns the 2D distance between (x1, y1) and (x2, y2).
QgsMapCanvas * mMapCanvas
pointer to map canvas
const QgsMapToPixel * getCoordinateTransform()
Gets the current coordinate transform.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
A mouse event which is the result of a user interaction with a QgsMapCanvas.
Perform transforms between map coordinates and device coordinates.
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
@ Edge
Snapped to an edge.
Contains information about the context of a rendering operation.
void setCoordinateTransform(const QgsCoordinateTransform &t)
Sets the current coordinate transform for the context.
double convertFromPainterUnits(double size, Qgis::RenderUnit unit) const
Converts a size from painter units (pixels) to the specified render unit.
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
Responsible for drawing transient features (e.g.
QgsRubberBand(QgsMapCanvas *mapCanvas, Qgis::GeometryType geometryType=Qgis::GeometryType::Line)
Creates a new RubberBand.
void setWidth(double width)
Sets the width of the line.
@ ICON_BOX
A box is used to highlight points (□).
void setColor(const QColor &color)
Sets the color for the rubberband.
static const QgsSettingsEntryColor * settingsDigitizingLineColor
Settings entry digitizing line color.
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
An interface for classes which can visit style entity (e.g.
@ SymbolRule
Rule based symbology or label child rule.
virtual bool visitEnter(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor starts visiting a node.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
A symbol entity for QgsStyle databases.
Abstract base class for symbol layers.
@ BlankSegments
String list of distance to define blank segments along line for templated line symbol layers.
QString id() const
Returns symbol layer identifier This id is unique in the whole project.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Base class for templated line symbols, e.g.
Represents a vector layer which manages a vector based dataset.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define QgsDebugError(str)
QgsFeatureId featureId() const
The id of the feature to which the snapped geometry belongs.
Contains information relating to a node (i.e.
QgsStyleEntityVisitorInterface::NodeType type
Node type.
Contains information relating to the style entity currently being visited.
const QgsStyleEntityInterface * entity
Reference to style entity being visited.