QGIS API Documentation  2.99.0-Master (e077efd)
qgsrubberband.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrubberband.cpp - Rubberband widget for drawing multilines and polygons
3  --------------------------------------
4  Date : 07-Jan-2006
5  Copyright : (C) 2006 by Tom Elwertowski
6  Email : telwertowski at users dot sourceforge dot net
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsrubberband.h"
17 #include "qgsfeature.h"
18 #include "qgsgeometry.h"
19 #include "qgslogger.h"
20 #include "qgsmapcanvas.h"
21 #include "qgsvectorlayer.h"
22 #include <QPainter>
23 
30  : QgsMapCanvasItem( mapCanvas )
31  , mIconSize( 5 )
32  , mIconType( ICON_CIRCLE )
33  , mGeometryType( geometryType )
34  , mTranslationOffsetX( 0.0 )
35  , mTranslationOffsetY( 0.0 )
36 {
37  reset( geometryType );
38  QColor color( Qt::lightGray );
39  color.setAlpha( 63 );
40  setColor( color );
41  setWidth( 1 );
42  setLineStyle( Qt::SolidLine );
43  setBrushStyle( Qt::SolidPattern );
44 }
45 
47  : QgsMapCanvasItem( nullptr )
48  , mIconSize( 5 )
49  , mIconType( ICON_CIRCLE )
50  , mGeometryType( QgsWkbTypes::PolygonGeometry )
51  , mTranslationOffsetX( 0.0 )
52  , mTranslationOffsetY( 0.0 )
53 {
54 }
55 
57 {
58 }
59 
63 void QgsRubberBand::setColor( const QColor & color )
64 {
65  setBorderColor( color );
66  setFillColor( color );
67 }
68 
72 void QgsRubberBand::setFillColor( const QColor & color )
73 {
74  QColor fillColor( color.red(), color.green(), color.blue(), color.alpha() );
75  mBrush.setColor( fillColor );
76 }
77 
81 void QgsRubberBand::setBorderColor( const QColor & color )
82 {
83  QColor penColor( color.red(), color.green(), color.blue(), color.alpha() );
84  mPen.setColor( penColor );
85 }
86 
87 
91 void QgsRubberBand::setWidth( int width )
92 {
93  mPen.setWidth( width );
94 }
95 
97 {
98  mIconType = icon;
99 }
100 
101 void QgsRubberBand::setIconSize( int iconSize )
102 {
103  mIconSize = iconSize;
104 }
105 
106 void QgsRubberBand::setLineStyle( Qt::PenStyle penStyle )
107 {
108  mPen.setStyle( penStyle );
109 }
110 
111 void QgsRubberBand::setBrushStyle( Qt::BrushStyle brushStyle )
112 {
113  mBrush.setStyle( brushStyle );
114 }
115 
120 {
121  mPoints.clear();
122  mGeometryType = geometryType;
123  updateRect();
124  update();
125 }
126 
130 void QgsRubberBand::addPoint( const QgsPoint & p, bool doUpdate /* = true */, int geometryIndex )
131 {
132  if ( geometryIndex < 0 )
133  {
134  geometryIndex = mPoints.size() - 1;
135  }
136 
137  if ( geometryIndex < 0 || geometryIndex > mPoints.size() )
138  {
139  return;
140  }
141 
142  if ( geometryIndex == mPoints.size() )
143  {
144  mPoints.push_back( QList<QgsPoint>() << p );
145  }
146 
147  if ( mPoints.at( geometryIndex ).size() == 2 &&
148  mPoints.at( geometryIndex ).at( 0 ) == mPoints.at( geometryIndex ).at( 1 ) )
149  {
150  mPoints[geometryIndex].last() = p;
151  }
152  else
153  {
154  mPoints[geometryIndex] << p;
155  }
156 
157 
158  if ( doUpdate )
159  {
160  setVisible( true );
161  updateRect();
162  update();
163  }
164 }
165 
166 void QgsRubberBand::closePoints( bool doUpdate, int geometryIndex )
167 {
168  if ( geometryIndex < 0 || geometryIndex >= mPoints.size() )
169  {
170  return;
171  }
172 
173  if ( mPoints.at( geometryIndex ).at( 0 ) != mPoints.at( geometryIndex ).at( mPoints.at( geometryIndex ).size() - 1 ) )
174  {
175  mPoints[geometryIndex] << mPoints.at( geometryIndex ).at( 0 );
176  }
177 
178  if ( doUpdate )
179  {
180  setVisible( true );
181  updateRect();
182  update();
183  }
184 }
185 
186 
187 void QgsRubberBand::removePoint( int index, bool doUpdate/* = true*/, int geometryIndex/* = 0*/ )
188 {
189 
190  if ( mPoints.size() < geometryIndex + 1 )
191  {
192  return;
193  }
194 
195 
196  if ( !mPoints[geometryIndex].isEmpty() )
197  {
198  // negative index removes from end, eg -1 removes last one
199  if ( index < 0 )
200  {
201  index = mPoints.at( geometryIndex ).size() + index;
202  }
203  mPoints[geometryIndex].removeAt( index );
204  }
205 
206  if ( doUpdate )
207  {
208  updateRect();
209  update();
210  }
211 }
212 
213 void QgsRubberBand::removeLastPoint( int geometryIndex, bool doUpdate/* = true*/ )
214 {
215  removePoint( -1, doUpdate, geometryIndex );
216 }
217 
221 void QgsRubberBand::movePoint( const QgsPoint & p, int geometryIndex )
222 {
223  if ( mPoints.size() < geometryIndex + 1 )
224  {
225  return;
226  }
227 
228  if ( mPoints.at( geometryIndex ).size() < 1 )
229  {
230  return;
231  }
232 
233  mPoints[geometryIndex].last() = p;
234 
235  updateRect();
236  update();
237 }
238 
239 void QgsRubberBand::movePoint( int index, const QgsPoint& p, int geometryIndex )
240 {
241  if ( mPoints.size() < geometryIndex + 1 )
242  {
243  return;
244  }
245 
246  if ( mPoints.at( geometryIndex ).size() < index )
247  {
248  return;
249  }
250 
251  mPoints[geometryIndex][index] = p;
252 
253  updateRect();
254  update();
255 }
256 
258 {
259  if ( geom.isEmpty() )
260  {
261  reset( mGeometryType );
262  return;
263  }
264 
265  reset( geom.type() );
266  addGeometry( geom, layer );
267 }
268 
270 {
271  if ( geom.isEmpty() )
272  {
273  return;
274  }
275 
276  //maprender object of canvas
277  const QgsMapSettings& ms = mMapCanvas->mapSettings();
278 
279  int idx = mPoints.size();
280 
281  switch ( geom.wkbType() )
282  {
283 
284  case QgsWkbTypes::Point:
286  {
287  QgsPoint pt;
288  if ( layer )
289  {
290  pt = ms.layerToMapCoordinates( layer, geom.asPoint() );
291  }
292  else
293  {
294  pt = geom.asPoint();
295  }
296  addPoint( pt, false, idx );
297  removeLastPoint( idx, false );
298  }
299  break;
300 
303  {
304  QgsMultiPoint mpt = geom.asMultiPoint();
305  for ( int i = 0; i < mpt.size(); ++i, ++idx )
306  {
307  QgsPoint pt = mpt[i];
308  if ( layer )
309  {
310  addPoint( ms.layerToMapCoordinates( layer, pt ), false, idx );
311  removeLastPoint( idx, false );
312  }
313  else
314  {
315  addPoint( pt, false, idx );
316  removeLastPoint( idx, false );
317  }
318  }
319  }
320  break;
321 
324  {
325  QgsPolyline line = geom.asPolyline();
326  for ( int i = 0; i < line.count(); i++ )
327  {
328  if ( layer )
329  {
330  addPoint( ms.layerToMapCoordinates( layer, line[i] ), false, idx );
331  }
332  else
333  {
334  addPoint( line[i], false, idx );
335  }
336  }
337  }
338  break;
339 
342  {
343 
344  QgsMultiPolyline mline = geom.asMultiPolyline();
345  for ( int i = 0; i < mline.size(); ++i, ++idx )
346  {
347  QgsPolyline line = mline[i];
348 
349  if ( line.isEmpty() )
350  {
351  --idx;
352  }
353 
354  for ( int j = 0; j < line.size(); ++j )
355  {
356  if ( layer )
357  {
358  addPoint( ms.layerToMapCoordinates( layer, line[j] ), false, idx );
359  }
360  else
361  {
362  addPoint( line[j], false, idx );
363  }
364  }
365  }
366  }
367  break;
368 
371  {
372  QgsPolygon poly = geom.asPolygon();
373  QgsPolyline line = poly[0];
374  for ( int i = 0; i < line.count(); i++ )
375  {
376  if ( layer )
377  {
378  addPoint( ms.layerToMapCoordinates( layer, line[i] ), false, idx );
379  }
380  else
381  {
382  addPoint( line[i], false, idx );
383  }
384  }
385  }
386  break;
387 
390  {
391 
392  QgsMultiPolygon multipoly = geom.asMultiPolygon();
393  for ( int i = 0; i < multipoly.size(); ++i, ++idx )
394  {
395  QgsPolygon poly = multipoly[i];
396  QgsPolyline line = poly[0];
397  for ( int j = 0; j < line.count(); ++j )
398  {
399  if ( layer )
400  {
401  addPoint( ms.layerToMapCoordinates( layer, line[j] ), false, idx );
402  }
403  else
404  {
405  addPoint( line[j], false, idx );
406  }
407  }
408  }
409  }
410  break;
411 
413  default:
414  return;
415  }
416 
417  setVisible( true );
418  updateRect();
419  update();
420 }
421 
423 {
424  if ( !mMapCanvas )
425  {
426  return;
427  }
428 
429  const QgsMapToPixel* transform = mMapCanvas->getCoordinateTransform();
430  QgsPoint ll = transform->toMapCoordinates( rect.left(), rect.bottom() );
431  QgsPoint lr = transform->toMapCoordinates( rect.right(), rect.bottom() );
432  QgsPoint ul = transform->toMapCoordinates( rect.left(), rect.top() );
433  QgsPoint ur = transform->toMapCoordinates( rect.right(), rect.top() );
434 
436  addPoint( ll, false );
437  addPoint( lr, false );
438  addPoint( ur, false );
439  addPoint( ul, true );
440 }
441 
445 void QgsRubberBand::paint( QPainter* p )
446 {
447  if ( !mPoints.isEmpty() )
448  {
449  p->setBrush( mBrush );
450  p->setPen( mPen );
451 
452  Q_FOREACH ( const QList<QgsPoint>& line, mPoints )
453  {
454  QVector<QPointF> pts;
455  Q_FOREACH ( const QgsPoint& pt, line )
456  {
457  const QPointF cur = toCanvasCoordinates( QgsPoint( pt.x() + mTranslationOffsetX, pt.y() + mTranslationOffsetY ) ) - pos();
458  if ( pts.empty() || std::abs( pts.back().x() - cur.x() ) > 1 || std::abs( pts.back().y() - cur.y() ) > 1 )
459  pts.append( cur );
460  }
461 
462  switch ( mGeometryType )
463  {
465  {
466  p->drawPolygon( pts );
467  }
468  break;
469 
471  {
472  Q_FOREACH ( QPointF pt, pts )
473  {
474  double x = pt.x();
475  double y = pt.y();
476 
477  qreal s = ( mIconSize - 1 ) / 2.0;
478 
479  switch ( mIconType )
480  {
481  case ICON_NONE:
482  break;
483 
484  case ICON_CROSS:
485  p->drawLine( QLineF( x - s, y, x + s, y ) );
486  p->drawLine( QLineF( x, y - s, x, y + s ) );
487  break;
488 
489  case ICON_X:
490  p->drawLine( QLineF( x - s, y - s, x + s, y + s ) );
491  p->drawLine( QLineF( x - s, y + s, x + s, y - s ) );
492  break;
493 
494  case ICON_BOX:
495  p->drawLine( QLineF( x - s, y - s, x + s, y - s ) );
496  p->drawLine( QLineF( x + s, y - s, x + s, y + s ) );
497  p->drawLine( QLineF( x + s, y + s, x - s, y + s ) );
498  p->drawLine( QLineF( x - s, y + s, x - s, y - s ) );
499  break;
500 
501  case ICON_FULL_BOX:
502  p->drawRect( x - s, y - s, mIconSize, mIconSize );
503  break;
504 
505  case ICON_CIRCLE:
506  p->drawEllipse( x - s, y - s, mIconSize, mIconSize );
507  break;
508  }
509  }
510  }
511  break;
512 
514  default:
515  {
516  p->drawPolyline( pts );
517  }
518  break;
519  }
520  }
521  }
522 }
523 
525 {
526  if ( mPoints.empty() )
527  {
528  setRect( QgsRectangle() );
529  setVisible( false );
530  return;
531  }
532 
533  const QgsMapToPixel& m2p = *( mMapCanvas->getCoordinateTransform() );
534 
535  qreal res = m2p.mapUnitsPerPixel();
536  qreal w = (( mIconSize - 1 ) / 2 + mPen.width() ) / res;
537 
538  QgsRectangle r;
539  for ( int i = 0; i < mPoints.size(); ++i )
540  {
541  QList<QgsPoint>::const_iterator it = mPoints.at( i ).constBegin(),
542  itE = mPoints.at( i ).constEnd();
543  for ( ; it != itE; ++it )
544  {
545  QgsPoint p( it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY );
546  p = m2p.transform( p );
547  QgsRectangle rect( p.x() - w, p.y() - w, p.x() + w, p.y() + w );
548 
549  if ( r.isEmpty() )
550  {
551  // Get rectangle of the first point
552  r = rect;
553  }
554  else
555  {
556  r.combineExtentWith( rect );
557  }
558  }
559  }
560 
561  // This is an hack to pass QgsMapCanvasItem::setRect what it
562  // expects (encoding of position and size of the item)
563  QgsPoint topLeft = m2p.toMapPoint( r.xMinimum(), r.yMinimum() );
564  QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + r.width()*res, topLeft.y() - r.height()*res );
565 
566  setRect( rect );
567 }
568 
570 {
571  // re-compute rectangle
572  // See http://hub.qgis.org/issues/12392
573  // NOTE: could be optimized by saving map-extent
574  // of rubberband and simply re-projecting
575  // that to device-rectange on "updatePosition"
576  updateRect();
577 }
578 
579 void QgsRubberBand::setTranslationOffset( double dx, double dy )
580 {
581  mTranslationOffsetX = dx;
582  mTranslationOffsetY = dy;
583  updateRect();
584 }
585 
587 {
588  return mPoints.size();
589 }
590 
591 int QgsRubberBand::partSize( int geometryIndex ) const
592 {
593  if ( geometryIndex < 0 || geometryIndex >= mPoints.size() ) return 0;
594  return mPoints[geometryIndex].size();
595 }
596 
598 {
599  int count = 0;
600  QList<QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
601  for ( ; it != mPoints.constEnd(); ++it )
602  {
603  QList<QgsPoint>::const_iterator iter = it->constBegin();
604  for ( ; iter != it->constEnd(); ++iter )
605  {
606  ++count;
607  }
608  }
609  return count;
610 }
611 
612 const QgsPoint *QgsRubberBand::getPoint( int i, int j ) const
613 {
614  if ( i < mPoints.size() && j < mPoints[i].size() )
615  return &mPoints[i][j];
616  else
617  return nullptr;
618 }
619 
621 {
622  QgsGeometry geom;
623 
624  switch ( mGeometryType )
625  {
627  {
628  QgsPolygon polygon;
629  QList< QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
630  for ( ; it != mPoints.constEnd(); ++it )
631  {
632  polygon.append( getPolyline( *it ) );
633  }
634  geom = QgsGeometry::fromPolygon( polygon );
635  break;
636  }
637 
639  {
640  QgsMultiPoint multiPoint;
641 
642  QList< QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
643  for ( ; it != mPoints.constEnd(); ++it )
644  {
645  multiPoint += getPolyline( *it );
646  }
647  geom = QgsGeometry::fromMultiPoint( multiPoint );
648  break;
649  }
650 
652  default:
653  {
654  if ( !mPoints.isEmpty() )
655  {
656  if ( mPoints.size() > 1 )
657  {
658  QgsMultiPolyline multiPolyline;
659  QList< QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
660  for ( ; it != mPoints.constEnd(); ++it )
661  {
662  multiPolyline.append( getPolyline( *it ) );
663  }
664  geom = QgsGeometry::fromMultiPolyline( multiPolyline );
665  }
666  else
667  {
668  geom = QgsGeometry::fromPolyline( getPolyline( mPoints.at( 0 ) ) );
669  }
670  }
671  break;
672  }
673  }
674  return geom;
675 }
676 
677 QgsPolyline QgsRubberBand::getPolyline( const QList<QgsPoint> & points )
678 {
679  QgsPolyline polyline;
680  QList<QgsPoint>::const_iterator iter = points.constBegin();
681  for ( ; iter != points.constEnd(); ++iter )
682  {
683  polyline.append( *iter );
684  }
685  return polyline;
686 }
QgsPolygon asPolygon() const
Return contents of the geometry as a polygon if wkbType is WKBPolygon, otherwise an empty list...
A cross is used to highlight points (x)
Definition: qgsrubberband.h:53
void setIconSize(int iconSize)
Set the size of the point icons.
void setWidth(int width)
Set the width of the line.
static unsigned index
QgsMultiPolyline asMultiPolyline() const
Return contents of the geometry as a multi linestring if wkbType is WKBMultiLineString, otherwise an empty list.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
double y
Definition: qgspoint.h:116
int numberOfVertices() const
Returns count of vertices in all lists of mPoint.
void setBorderColor(const QColor &color)
Set the border color for the rubberband.
QgsPoint asPoint() const
Return contents of the geometry as a point if wkbType is WKBPoint, otherwise returns [0...
QgsRectangle rect() const
returns canvas item rectangle in map units
void setToCanvasRectangle(QRect rect)
Sets this rubber band to a map canvas rectangle.
static QgsGeometry fromPolyline(const QgsPolyline &polyline)
Creates a new geometry from a QgsPolyline object.
void setTranslationOffset(double dx, double dy)
Adds translation to original coordinates (all in map coordinates)
void setLineStyle(Qt::PenStyle penStyle)
Set the style of the line.
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
void movePoint(const QgsPoint &p, int geometryIndex=0)
Moves the rubber band point specified by index.
QVector< QgsPoint > QgsPolyline
Polyline is represented as a vector of points.
Definition: qgsgeometry.h:46
An abstract class for items that can be placed on the map canvas.
QgsPoint toMapPoint(double x, double y) const
QgsPoint toMapCoordinates(int x, int y) const
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:78
virtual void updatePosition() override
called on changed extent or resize event to update position of the item
A cross is used to highlight points (+)
Definition: qgsrubberband.h:48
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:106
const QgsPoint * getPoint(int i, int j=0) const
Return vertex.
QgsPolyline asPolyline() const
Return contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list...
virtual void paint(QPainter *p) override
The QgsMapSettings class contains configuration for rendering of the map.
void setToGeometry(const QgsGeometry &geom, QgsVectorLayer *layer)
Sets this rubber band to the geometry of an existing feature.
QgsRubberBand(QgsMapCanvas *mapCanvas, QgsWkbTypes::GeometryType geometryType=QgsWkbTypes::LineGeometry)
Creates a new RubberBand.
QPointF toCanvasCoordinates(const QgsPoint &point) const
transformation from map coordinates to screen coordinates
QgsMultiPoint asMultiPoint() const
Return contents of the geometry as a multi point if wkbType is WKBMultiPoint, otherwise an empty list...
QgsPoint transform(const QgsPoint &p) const
Transform the point from map (world) coordinates to device coordinates.
void closePoints(bool doUpdate=true, int geometryIndex=0)
Ensures that a polygon geometry is closed and that the last vertex equals the first vertex...
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:33
QgsGeometry asGeometry() const
Returns the rubberband as a Geometry.
bool isEmpty() const
test if rectangle is empty.
A circle is used to highlight points (○)
Definition: qgsrubberband.h:63
void addGeometry(const QgsGeometry &geom, QgsVectorLayer *layer)
Add the geometry of an existing feature to a rubberband This is useful for multi feature highlighting...
void removePoint(int index=0, bool doUpdate=true, int geometryIndex=0)
Remove a vertex from the rubberband and (optionally) update canvas.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:211
void setRect(const QgsRectangle &r, bool resetRotation=true)
sets canvas item rectangle in map units
QVector< QgsPolygon > QgsMultiPolygon
A collection of QgsPolygons that share a common collection of attributes.
Definition: qgsgeometry.h:61
void addPoint(const QgsPoint &p, bool doUpdate=true, int geometryIndex=0)
Add a vertex to the rubberband and update canvas.
QVector< QgsPoint > QgsMultiPoint
A collection of QgsPoints that share a common collection of attributes.
Definition: qgsgeometry.h:55
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
void setFillColor(const QColor &color)
Set the fill color for the rubberband.
QVector< QgsPolyline > QgsPolygon
Polygon: first item of the list is outer ring, inner rings (if any) start from second item...
Definition: qgsgeometry.h:52
double mapUnitsPerPixel() const
Return current map units per pixel.
A class to represent a point.
Definition: qgspoint.h:111
QgsWkbTypes::GeometryType type() const
Returns type of the geometry as a QgsWkbTypes::GeometryType.
static QgsGeometry fromPolygon(const QgsPolygon &polygon)
Creates a new geometry from a QgsPolygon.
QgsMapCanvasItem(QgsMapCanvas *mapCanvas)
protected constructor: cannot be constructed directly
void setBrushStyle(Qt::BrushStyle brushStyle)
Set the style of the brush.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:206
QVector< QgsPolyline > QgsMultiPolyline
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:58
const QgsMapSettings & mapSettings() const
Get access to properties used for map rendering.
void combineExtentWith(const QgsRectangle &rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
void setIcon(IconType icon)
Set the icon type to highlight point geometries.
A box is used to highlight points (□)
Definition: qgsrubberband.h:58
QgsPoint layerToMapCoordinates(QgsMapLayer *theLayer, QgsPoint point) const
transform point coordinates from layer&#39;s CRS to output CRS
static QgsGeometry fromMultiPoint(const QgsMultiPoint &multipoint)
Creates a new geometry from a QgsMultiPoint object.
QgsMultiPolygon asMultiPolygon() const
Return contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty ...
int partSize(int geometryIndex) const
Returns number of vertices in feature part.
QgsMapCanvas * mMapCanvas
pointer to map canvas
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:196
const QgsMapToPixel * getCoordinateTransform()
Get the current coordinate transform.
void reset(QgsWkbTypes::GeometryType geometryType=QgsWkbTypes::LineGeometry)
Clears all the geometries in this rubberband.
void setColor(const QColor &color)
Set the color for the rubberband.
No icon is used.
Definition: qgsrubberband.h:43
int size() const
Returns number of geometries.
Represents a vector layer which manages a vector based data sets.
void removeLastPoint(int geometryIndex=0, bool doUpdate=true)
Removes the last point.
void updateRect()
recalculates needed rectangle
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:216
A full box is used to highlight points (■)
Definition: qgsrubberband.h:68
static QgsGeometry fromMultiPolyline(const QgsMultiPolyline &multiline)
Creates a new geometry from a QgsMultiPolyline object.
double x
Definition: qgspoint.h:115