QGIS API Documentation  3.27.0-Master (0e23467727)
qgsgeometryrubberband.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometryrubberband.cpp
3  -------------------------
4  begin : December 2014
5  copyright : (C) 2014 by Marco Hugentobler
6  email : marco at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsgeometryrubberband.h"
19 #include "qgsabstractgeometry.h"
20 #include "qgsmapcanvas.h"
21 #include "qgsrendercontext.h"
22 #include "qgspoint.h"
23 #include <QPainter>
24 
26  mIconSize( 5 ), mIconType( ICON_BOX ), mGeometryType( geomType )
27 {
28  mPen = QPen( QColor( 255, 0, 0 ) );
29  mBrush = QBrush( QColor( 255, 0, 0 ) );
30 }
31 
33 {
34 }
35 
36 void QgsGeometryRubberBand::paint( QPainter *painter )
37 {
38  if ( !mGeometry || !painter )
39  {
40  return;
41  }
42 
43  const QgsScopedQPainterState painterState( painter );
44  painter->translate( -pos() );
45 
46  if ( mGeometryType == QgsWkbTypes::PolygonGeometry )
47  {
48  painter->setBrush( mBrush );
49  }
50  else
51  {
52  painter->setBrush( Qt::NoBrush );
53  }
54  painter->setPen( mPen );
55 
56 
57  std::unique_ptr< QgsAbstractGeometry > paintGeom( mGeometry->clone() );
58 
59  paintGeom->transform( mMapCanvas->getCoordinateTransform()->transform() );
60  paintGeom->draw( *painter );
61 
62  if ( !mDrawVertices )
63  return;
64 
65  //draw vertices
66  QgsVertexId vertexId;
67  QgsPoint vertex;
68  while ( paintGeom->nextVertex( vertexId, vertex ) )
69  {
70  drawVertex( painter, vertex.x(), vertex.y() );
71  }
72 }
73 
75 {
76  return mGeometryType;
77 }
78 
80 {
81  mGeometryType = geometryType;
82 }
83 
84 void QgsGeometryRubberBand::drawVertex( QPainter *p, double x, double y )
85 {
86  const qreal s = ( mIconSize - 1 ) / 2.0;
87 
88  switch ( mIconType )
89  {
90  case ICON_NONE:
91  break;
92 
93  case ICON_CROSS:
94  p->drawLine( QLineF( x - s, y, x + s, y ) );
95  p->drawLine( QLineF( x, y - s, x, y + s ) );
96  break;
97 
98  case ICON_X:
99  p->drawLine( QLineF( x - s, y - s, x + s, y + s ) );
100  p->drawLine( QLineF( x - s, y + s, x + s, y - s ) );
101  break;
102 
103  case ICON_BOX:
104  p->drawLine( QLineF( x - s, y - s, x + s, y - s ) );
105  p->drawLine( QLineF( x + s, y - s, x + s, y + s ) );
106  p->drawLine( QLineF( x + s, y + s, x - s, y + s ) );
107  p->drawLine( QLineF( x - s, y + s, x - s, y - s ) );
108  break;
109 
110  case ICON_FULL_BOX:
111  p->drawRect( x - s, y - s, mIconSize, mIconSize );
112  break;
113 
114  case ICON_CIRCLE:
115  p->drawEllipse( x - s, y - s, mIconSize, mIconSize );
116  break;
117  }
118 }
119 
121 {
122  mGeometry.reset( geom );
123 
124  if ( mGeometry )
125  {
126  setRect( rubberBandRectangle() );
127  }
128 }
129 
131 {
132  if ( mGeometry )
133  {
134  mGeometry->moveVertex( id, newPos );
135  setRect( rubberBandRectangle() );
136  }
137 }
138 
140 {
141  mBrush.setColor( c );
142 }
143 
145 {
146  mPen.setColor( c );
147 }
148 
150 {
151  mPen.setWidth( width );
152 }
153 
154 void QgsGeometryRubberBand::setLineStyle( Qt::PenStyle penStyle )
155 {
156  mPen.setStyle( penStyle );
157 }
158 
159 void QgsGeometryRubberBand::setBrushStyle( Qt::BrushStyle brushStyle )
160 {
161  mBrush.setStyle( brushStyle );
162 }
163 
165 {
166  mDrawVertices = isVerticesDrawn;
167 }
168 
169 QgsRectangle QgsGeometryRubberBand::rubberBandRectangle() const
170 {
171  if ( !mGeometry || mGeometry->isEmpty() )
172  {
173  return QgsRectangle();
174  }
175  const QgsMapToPixel &m2p = *( mMapCanvas->getCoordinateTransform() );
176 
177  qreal w = ( ( mIconSize - 1 ) / 2 + mPen.width() ); // in canvas units
178 
179  QgsRectangle r; // in canvas units
180  QgsRectangle rectMap = mGeometry->boundingBox(); // in map units
181  QList<QgsPointXY> pl;
182  pl << QgsPointXY( rectMap.xMinimum(), rectMap.yMinimum() )
183  << QgsPointXY( rectMap.xMinimum(), rectMap.yMaximum() )
184  << QgsPointXY( rectMap.xMaximum(), rectMap.yMaximum() )
185  << QgsPointXY( rectMap.xMaximum(), rectMap.yMinimum() );
186 
187  for ( QgsPointXY &p : pl )
188  {
189  p = toCanvasCoordinates( p );
190  // no need to normalize the rectangle -- we know it is already normal
191  QgsRectangle rect( p.x() - w, p.y() - w, p.x() + w, p.y() + w, false );
192  r.combineExtentWith( rect );
193  }
194 
195  // This is an hack to pass QgsMapCanvasItem::setRect what it
196  // expects (encoding of position and size of the item)
197  qreal res = m2p.mapUnitsPerPixel();
198  QgsPointXY topLeft = m2p.toMapCoordinates( r.xMinimum(), r.yMinimum() );
199  QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + r.width()*res, topLeft.y() - r.height()*res );
200 
201  return rect;
202 }
203 
205 {
206  // re-compute rectangle
207  // See https://github.com/qgis/QGIS/issues/20566
208  // NOTE: could be optimized by saving map-extent
209  // of rubberband and simply re-projecting
210  // that to device-rectangle on "updatePosition"
211  setRect( rubberBandRectangle() );
212 }
Abstract base class for all geometries.
void setStrokeColor(const QColor &c)
Sets stroke color for vertex markers.
@ ICON_X
A cross is used to highlight points (x)
@ ICON_NONE
No icon is used.
@ ICON_FULL_BOX
A full box is used to highlight points (■)
@ ICON_CIRCLE
A circle is used to highlight points (○)
@ ICON_BOX
A box is used to highlight points (□)
@ ICON_CROSS
A cross is used to highlight points (+)
QgsWkbTypes::GeometryType geometryType() const
Returns which geometry is handled by the rubber band, polygon or line.
void setBrushStyle(Qt::BrushStyle brushStyle)
Sets brush style.
void setGeometryType(const QgsWkbTypes::GeometryType &geometryType)
Sets which geometry is handled by the rubber band, polygon or line.
void updatePosition() override
called on changed extent or resize event to update position of the item
void setLineStyle(Qt::PenStyle penStyle)
Sets pen style.
virtual void setGeometry(QgsAbstractGeometry *geom)
Sets geometry (takes ownership). Geometry is expected to be in map coordinates.
void paint(QPainter *painter) override
function to be implemented by derived classes
void moveVertex(QgsVertexId id, const QgsPoint &newPos)
Moves vertex to new position (in map coordinates)
void setStrokeWidth(int width)
Sets stroke width.
void setVertexDrawingEnabled(bool isVerticesDrawn)
Sets whether the vertices are drawn.
QgsGeometryRubberBand(QgsMapCanvas *mapCanvas, QgsWkbTypes::GeometryType geomType=QgsWkbTypes::LineGeometry)
void setFillColor(const QColor &c)
Sets fill color for vertex markers.
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.
Definition: qgsmapcanvas.h:90
const QgsMapToPixel * getCoordinateTransform()
Gets the current coordinate transform.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:39
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.
Definition: qgsmaptopixel.h:90
A class to represent a 2D point.
Definition: qgspointxy.h:59
double y
Definition: qgspointxy.h:63
Q_GADGET double x
Definition: qgspointxy.h:62
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
Q_GADGET double x
Definition: qgspoint.h:52
double y
Definition: qgspoint.h:53
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:391
Scoped object for saving and restoring a QPainter object's state.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:141
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
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:31