17#include "moc_qgsrubberband.cpp"
35 , mGeometryType( geometryType )
37 reset( geometryType );
38 QColor color( Qt::lightGray );
47QgsRubberBand::QgsRubberBand()
63 if ( mBrush.color() == color )
66 mBrush.setColor( color );
71 mPen.setColor( color );
76 mSecondaryPen.setColor( color );
81 mPen.setWidthF(
width );
92 mSvgRenderer = std::make_unique<QSvgRenderer>( path );
93 mSvgOffset = drawOffset;
103 mPen.setStyle( penStyle );
108 mBrush.setStyle( brushStyle );
114 mGeometryType = geometryType;
121 if ( geometryIndex < 0 )
123 geometryIndex = mPoints.size() - 1;
126 if ( geometryIndex < 0 || geometryIndex > mPoints.size() )
131 if ( geometryIndex == mPoints.size() )
142 if ( mPoints.at( geometryIndex ).isEmpty() )
145 ringIndex = mPoints.at( geometryIndex ).size() - 1;
148 if ( ringIndex > mPoints.at( geometryIndex ).size() )
151 if ( ringIndex == mPoints.at( geometryIndex ).size() )
155 mPoints[geometryIndex][ringIndex].append( p );
158 if ( mPoints.at( geometryIndex ).at( ringIndex ).size() == 2 &&
159 mPoints.at( geometryIndex ).at( ringIndex ).at( 0 ) == mPoints.at( geometryIndex ).at( ringIndex ).at( 1 ) )
161 mPoints[geometryIndex][ringIndex].last() = p;
165 mPoints[geometryIndex][ringIndex].append( p );
179 if ( geometryIndex < 0 || ringIndex < 0 ||
180 mPoints.size() <= geometryIndex ||
181 mPoints.at( geometryIndex ).size() <= ringIndex ||
182 mPoints.at( geometryIndex ).at( ringIndex ).isEmpty() )
187 if ( mPoints.at( geometryIndex ).at( ringIndex ).constFirst() != mPoints.at( geometryIndex ).at( ringIndex ).constLast() )
189 mPoints[geometryIndex][ringIndex].append( mPoints.at( geometryIndex ).at( ringIndex ).constFirst() );
204 if ( geometryIndex < 0 || ringIndex < 0 ||
205 mPoints.size() <= geometryIndex ||
206 mPoints.at( geometryIndex ).size() <= ringIndex ||
207 mPoints.at( geometryIndex ).at( ringIndex ).size() <= index ||
208 mPoints.at( geometryIndex ).at( ringIndex ).size() < -index ||
209 mPoints.at( geometryIndex ).at( ringIndex ).isEmpty() )
217 index = mPoints.at( geometryIndex ).at( ringIndex ).size() + index;
219 mPoints[geometryIndex][ringIndex].removeAt( index );
230 removePoint( -1, doUpdate, geometryIndex, ringIndex );
235 if ( geometryIndex < 0 || ringIndex < 0 ||
236 mPoints.size() <= geometryIndex ||
237 mPoints.at( geometryIndex ).size() <= ringIndex ||
238 mPoints.at( geometryIndex ).at( ringIndex ).isEmpty() )
243 mPoints[geometryIndex][ringIndex].last() = p;
251 if ( geometryIndex < 0 || ringIndex < 0 || index < 0 ||
252 mPoints.size() <= geometryIndex ||
253 mPoints.at( geometryIndex ).size() <= ringIndex ||
254 mPoints.at( geometryIndex ).at( ringIndex ).size() <= index )
259 mPoints[geometryIndex][ringIndex][index] = p;
269 reset( mGeometryType );
281 reset( mGeometryType );
318 int idx = mPoints.size();
330 QgsDebugError( QStringLiteral(
"Could not transform rubber band geometry to map CRS" ) );
363 if ( line.isEmpty() )
382 addPoint( pt,
false, idx, ringIdx );
392 if ( poly.isEmpty() )
400 addPoint( pt,
false, idx, ringIdx );
442 reset( other->mGeometryType );
443 mPoints = other->mPoints;
450 if ( mPoints.isEmpty() )
453 QVector< QVector<QPolygonF> > shapes;
454 shapes.reserve( mPoints.size() );
455 for (
const QgsPolygonXY &poly : std::as_const( mPoints ) )
457 QVector<QPolygonF> rings;
458 rings.reserve( poly.size() );
461 QVector<QPointF> pts;
462 pts.reserve( line.size() );
466 if ( pts.isEmpty() || std::abs( pts.last().x() - cur.x() ) > 1 || std::abs( pts.last().y() - cur.y() ) > 1 )
471 shapes.append( rings );
479 lineSymbol->startRender( context );
480 for (
const QVector<QPolygonF> &shape : std::as_const( shapes ) )
482 for (
const QPolygonF &ring : shape )
484 lineSymbol->renderPolyline( ring,
nullptr, context );
487 lineSymbol->stopRender( context );
494 fillSymbol->startRender( context );
495 for (
const QVector<QPolygonF> &shape : std::as_const( shapes ) )
497 for (
const QPolygonF &ring : shape )
499 fillSymbol->renderPolygon( ring,
nullptr,
nullptr, context );
502 fillSymbol->stopRender( context );
506 int iterations = mSecondaryPen.color().isValid() ? 2 : 1;
507 for (
int i = 0; i < iterations; ++i )
509 if ( i == 0 && iterations > 1 )
513 p->setBrush( Qt::NoBrush );
514 p->setPen( mSecondaryPen );
519 p->setBrush( mBrush );
523 for (
const QVector<QPolygonF> &shape : std::as_const( shapes ) )
533 if ( rings.size() == 1 )
540 for (
const QPolygonF &poly : rings )
542 path.addPolygon( poly );
550 switch ( mGeometryType )
554 p->drawPolygon( pts );
560 const auto constPts = pts;
561 for ( QPointF pt : constPts )
566 qreal s = ( mIconSize - 1 ) / 2.0;
574 p->drawLine( QLineF( x - s, y, x + s, y ) );
575 p->drawLine( QLineF( x, y - s, x, y + s ) );
579 p->drawLine( QLineF( x - s, y - s, x + s, y + s ) );
580 p->drawLine( QLineF( x - s, y + s, x + s, y - s ) );
584 p->drawLine( QLineF( x - s, y - s, x + s, y - s ) );
585 p->drawLine( QLineF( x + s, y - s, x + s, y + s ) );
586 p->drawLine( QLineF( x + s, y + s, x - s, y + s ) );
587 p->drawLine( QLineF( x - s, y + s, x - s, y - s ) );
591 p->drawRect( QRectF(
static_cast< int>( x - s ),
static_cast< int >( y - s ), mIconSize, mIconSize ) );
595 p->drawEllipse( QRectF(
static_cast< int >( x - s ),
static_cast< int >( y - s ), mIconSize, mIconSize ) );
609 p->drawPolygon( pts, 4 );
611 p->drawPolyline( pts, 4 );
617 QRectF viewBox = mSvgRenderer->viewBoxF();
618 QRectF r( mSvgOffset.x(), mSvgOffset.y(), viewBox.width(), viewBox.height() );
621 mSvgRenderer->render( p, r );
632 p->drawPolyline( pts );
640 if ( mPoints.isEmpty() )
650 double iconSize = ( mIconSize + 1 ) / 2.;
653 QRectF viewBox = mSvgRenderer->viewBoxF();
654 iconSize = std::max( std::fabs( mSvgOffset.x() ) + .5 * viewBox.width(), std::fabs( mSvgOffset.y() ) + .5 * viewBox.height() );
658 qreal w = ( ( mIconSize - 1 ) / 2 + mPen.widthF() );
661 for (
const QgsPolygonXY &poly : std::as_const( mPoints ) )
663 for (
const QgsPointXY &point : poly.at( 0 ) )
665 QgsPointXY p( point.x() + mTranslationOffsetX, point.y() + mTranslationOffsetY );
684 return mSymbol.get();
704 mTranslationOffsetX = dx;
705 mTranslationOffsetY = dy;
711 return mPoints.size();
716 if ( geometryIndex < 0 ||
717 geometryIndex >= mPoints.size() ||
718 mPoints.at( geometryIndex ).isEmpty() )
720 return mPoints.at( geometryIndex ).at( 0 ).size();
726 for (
const QgsPolygonXY &poly : std::as_const( mPoints ) )
730 count += ring.size();
738 if ( i < 0 || ringIndex < 0 || j < 0 ||
739 mPoints.size() <= i ||
740 mPoints.at( i ).size() <= ringIndex ||
741 mPoints.at( i ).at( ringIndex ).size() <= j )
744 return &mPoints[i][ringIndex][j];
751 switch ( mGeometryType )
763 for (
const QgsPolygonXY &poly : std::as_const( mPoints ) )
765 if ( poly.isEmpty() )
767 multiPoint.append( poly.at( 0 ) );
776 if ( !mPoints.isEmpty() )
778 if ( mPoints.size() > 1 )
781 for (
const QgsPolygonXY &poly : std::as_const( mPoints ) )
783 if ( poly.isEmpty() )
785 multiPolyline.append( poly.at( 0 ) );
791 if ( !mPoints.at( 0 ).isEmpty() )
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
@ Antialiasing
Use antialiasing while drawing.
WkbType
The WKB type describes the number of dimensions a geometry has.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Custom exception class for Coordinate Reference System related exceptions.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
A geometry is the spatial representation of a feature.
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
static QgsGeometry fromMultiPolylineXY(const QgsMultiPolylineXY &multiline)
Creates a new geometry from a QgsMultiPolylineXY object.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
QgsMultiPointXY asMultiPoint() const
Returns the contents of the geometry as a multi-point.
QgsPolygonXY asPolygon() const
Returns the contents of the geometry as a polygon.
static QgsGeometry fromMultiPointXY(const QgsMultiPointXY &multipoint)
Creates a new geometry from a QgsMultiPointXY object.
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
static QgsGeometry fromMultiPolygonXY(const QgsMultiPolygonXY &multipoly)
Creates a new geometry from a QgsMultiPolygonXY.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
A line symbol type, for rendering LineString and MultiLineString geometries.
An abstract class for items that can be placed on the map canvas.
QgsRectangle rect() const
returns canvas item rectangle in map units
QPointF toCanvasCoordinates(const QgsPointXY &point) const
transformation from map coordinates to screen coordinates
QgsMapCanvas * mMapCanvas
pointer to map canvas
void setRect(const QgsRectangle &r, bool resetRotation=true)
sets canvas item rectangle in map units
Map canvas is a class for displaying all GIS data types on a canvas.
const QgsMapToPixel * getCoordinateTransform()
Gets the current coordinate transform.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
Base class for all map layer types.
The QgsMapSettings class contains configuration for rendering of the map.
QgsCoordinateTransform layerTransform(const QgsMapLayer *layer) const
Returns the coordinate transform from layer's CRS to destination CRS.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
Perform transforms between map coordinates and device coordinates.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
QgsPointXY transform(const QgsPointXY &p) const
Transforms a point p from map (world) coordinates to device coordinates.
A class to represent a 2D point.
static QgsProject * instance()
Returns the QgsProject singleton instance.
A rectangle specified with double values.
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Contains information about the context of a rendering operation.
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
A class for drawing transient features (e.g.
void setIconSize(double iconSize)
Sets the size of the point icons.
void closePoints(bool doUpdate=true, int geometryIndex=0, int ringIndex=0)
Ensures that a polygon geometry is closed and that the last vertex equals the first vertex.
~QgsRubberBand() override
void setSymbol(QgsSymbol *symbol)
Sets the symbol used for rendering the rubberband.
void removeLastPoint(int geometryIndex=0, bool doUpdate=true, int ringIndex=0)
Removes the last point.
void movePoint(const QgsPointXY &p, int geometryIndex=0, int ringIndex=0)
Moves the rubber band point specified by index.
QgsRubberBand(QgsMapCanvas *mapCanvas, Qgis::GeometryType geometryType=Qgis::GeometryType::Line)
Creates a new RubberBand.
QgsGeometry asGeometry() const
Returns the rubberband as a Geometry.
int size() const
Returns number of geometries.
void paint(QPainter *p) override
Paints the rubber band in response to an update event.
IconType icon() const
Returns the current icon type to highlight point geometries.
int partSize(int geometryIndex) const
Returns number of vertices in feature part.
void setSvgIcon(const QString &path, QPoint drawOffset)
Set the path to the svg file to use to draw points.
void setWidth(double width)
Sets the width of the line.
void reset(Qgis::GeometryType geometryType=Qgis::GeometryType::Line)
Clears all the geometries in this rubberband.
void setSecondaryStrokeColor(const QColor &color)
Sets a secondary stroke color for the rubberband which will be drawn under the main stroke color.
@ ICON_X
A cross is used to highlight points (x)
@ ICON_FULL_DIAMOND
A diamond is used to highlight points (◆)
@ ICON_FULL_BOX
A full box is used to highlight points (■)
@ ICON_NONE
No icon is used.
@ ICON_CROSS
A cross is used to highlight points (+)
@ ICON_SVG
An svg image is used to highlight points.
@ ICON_CIRCLE
A circle is used to highlight points (○)
@ ICON_DIAMOND
A diamond is used to highlight points (◇)
@ ICON_BOX
A box is used to highlight points (□)
const QgsPointXY * getPoint(int i, int j=0, int ringIndex=0) const
Returns a vertex.
void setColor(const QColor &color)
Sets the color for the rubberband.
void setToGeometry(const QgsGeometry &geom, QgsVectorLayer *layer)
Sets this rubber band to geom.
void setStrokeColor(const QColor &color)
Sets the stroke color for the rubberband.
void setLineStyle(Qt::PenStyle penStyle)
Sets the style of the line.
void updateRect()
Recalculates needed rectangle.
QgsSymbol * symbol() const
Returns the symbol used for rendering the rubberband, if set.
void setToCanvasRectangle(QRect rect)
Sets this rubber band to a map canvas rectangle.
void setIcon(IconType icon)
Sets the icon type to highlight point geometries.
void setBrushStyle(Qt::BrushStyle brushStyle)
Sets the style of the brush.
void updatePosition() override
called on changed extent or resize event to update position of the item
void copyPointsFrom(const QgsRubberBand *other)
Copies the points from another rubber band.
int numberOfVertices() const
Returns count of vertices in all lists of mPoint.
void addGeometry(const QgsGeometry &geometry, QgsMapLayer *layer, bool doUpdate=true)
Adds the geometry of an existing feature to a rubberband This is useful for multi feature highlightin...
void removePoint(int index=0, bool doUpdate=true, int geometryIndex=0, int ringIndex=0)
Removes a vertex from the rubberband and (optionally) updates canvas.
void setTranslationOffset(double dx, double dy)
Adds translation to original coordinates (all in map coordinates)
void setFillColor(const QColor &color)
Sets the fill color for the rubberband.
void drawShape(QPainter *p, const QVector< QPointF > &pts)
Draws shape of the rubber band.
void addPoint(const QgsPointXY &p, bool doUpdate=true, int geometryIndex=0, int ringIndex=0)
Adds a vertex to the rubberband and update canvas.
Scoped object for saving and restoring a QPainter object's state.
Abstract base class for all rendered symbols.
Represents a vector layer which manages a vector based data sets.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static bool isMultiType(Qgis::WkbType type)
Returns true if the WKB type is a multi type.
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
#define QgsDebugError(str)
const QgsCoordinateReferenceSystem & crs