QGIS API Documentation  3.17.0-Master (7a14973234)
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 "qgsgeometry.h"
18 #include "qgslogger.h"
19 #include "qgsmapcanvas.h"
20 #include "qgsvectorlayer.h"
21 #include "qgsproject.h"
22 #include "qgsrectangle.h"
23 #include <QPainter>
24 
26  : QObject( nullptr )
27  , QgsMapCanvasItem( mapCanvas )
28  , mGeometryType( geometryType )
29 {
30  reset( geometryType );
31  QColor color( Qt::lightGray );
32  color.setAlpha( 63 );
33  setColor( color );
34  setWidth( 1 );
35  setLineStyle( Qt::SolidLine );
36  setBrushStyle( Qt::SolidPattern );
37  setSecondaryStrokeColor( QColor() );
38 }
39 
41  : QObject( nullptr )
42  , QgsMapCanvasItem( nullptr )
43 {
44 }
45 
46 void QgsRubberBand::setColor( const QColor &color )
47 {
48  setStrokeColor( color );
49  setFillColor( color );
50 }
51 
52 void QgsRubberBand::setFillColor( const QColor &color )
53 {
54  if ( mBrush.color() == color )
55  return;
56 
57  mBrush.setColor( color );
58 }
59 
60 void QgsRubberBand::setStrokeColor( const QColor &color )
61 {
62  mPen.setColor( color );
63 }
64 
65 void QgsRubberBand::setSecondaryStrokeColor( const QColor &color )
66 {
67  mSecondaryPen.setColor( color );
68 }
69 
71 {
72  mPen.setWidth( width );
73 }
74 
76 {
77  mIconType = icon;
78 }
79 
80 void QgsRubberBand::setSvgIcon( const QString &path, QPoint drawOffset )
81 {
82  setIcon( ICON_SVG );
83  mSvgRenderer = qgis::make_unique<QSvgRenderer>( path );
84  mSvgOffset = drawOffset;
85 }
86 
88 {
89  mIconSize = iconSize;
90 }
91 
92 void QgsRubberBand::setLineStyle( Qt::PenStyle penStyle )
93 {
94  mPen.setStyle( penStyle );
95 }
96 
97 void QgsRubberBand::setBrushStyle( Qt::BrushStyle brushStyle )
98 {
99  mBrush.setStyle( brushStyle );
100 }
101 
103 {
104  mPoints.clear();
105  mGeometryType = geometryType;
106  updateRect();
107  update();
108 }
109 
110 void QgsRubberBand::addPoint( const QgsPointXY &p, bool doUpdate /* = true */, int geometryIndex, int ringIndex )
111 {
112  if ( geometryIndex < 0 )
113  {
114  geometryIndex = mPoints.size() - 1;
115  }
116 
117  if ( geometryIndex < 0 || geometryIndex > mPoints.size() )
118  {
119  return;
120  }
121 
122  if ( geometryIndex == mPoints.size() )
123  {
124  // since we're adding a geometry, ringIndex must be 0 or negative for last ring
125  if ( ringIndex > 0 )
126  return;
127  mPoints.append( QgsPolygonXY() );
128  }
129 
130  // negative ringIndex means last ring
131  if ( ringIndex < 0 )
132  {
133  if ( mPoints.at( geometryIndex ).isEmpty() )
134  ringIndex = 0;
135  else
136  ringIndex = mPoints.at( geometryIndex ).size() - 1;
137  }
138 
139  if ( ringIndex > mPoints.at( geometryIndex ).size() )
140  return;
141 
142  if ( ringIndex == mPoints.at( geometryIndex ).size() )
143  {
144  mPoints[geometryIndex].append( QgsPolylineXY() );
145  mPoints[geometryIndex][ringIndex].append( p );
146  }
147 
148  if ( mPoints.at( geometryIndex ).at( ringIndex ).size() == 2 &&
149  mPoints.at( geometryIndex ).at( ringIndex ).at( 0 ) == mPoints.at( geometryIndex ).at( ringIndex ).at( 1 ) )
150  {
151  mPoints[geometryIndex][ringIndex].last() = p;
152  }
153  else
154  {
155  mPoints[geometryIndex][ringIndex].append( p );
156  }
157 
158 
159  if ( doUpdate )
160  {
161  setVisible( true );
162  updateRect();
163  update();
164  }
165 }
166 
167 void QgsRubberBand::closePoints( bool doUpdate, int geometryIndex, int ringIndex )
168 {
169  if ( geometryIndex < 0 || ringIndex < 0 ||
170  mPoints.size() <= geometryIndex ||
171  mPoints.at( geometryIndex ).size() <= ringIndex ||
172  mPoints.at( geometryIndex ).at( ringIndex ).isEmpty() )
173  {
174  return;
175  }
176 
177  if ( mPoints.at( geometryIndex ).at( ringIndex ).constFirst() != mPoints.at( geometryIndex ).at( ringIndex ).constLast() )
178  {
179  mPoints[geometryIndex][ringIndex].append( mPoints.at( geometryIndex ).at( ringIndex ).constFirst() );
180  }
181 
182  if ( doUpdate )
183  {
184  setVisible( true );
185  updateRect();
186  update();
187  }
188 }
189 
190 
191 void QgsRubberBand::removePoint( int index, bool doUpdate/* = true*/, int geometryIndex/* = 0*/, int ringIndex/* = 0*/ )
192 {
193 
194  if ( geometryIndex < 0 || ringIndex < 0 ||
195  mPoints.size() <= geometryIndex ||
196  mPoints.at( geometryIndex ).size() <= ringIndex ||
197  mPoints.at( geometryIndex ).at( ringIndex ).size() <= index ||
198  mPoints.at( geometryIndex ).at( ringIndex ).size() < -index ||
199  mPoints.at( geometryIndex ).at( ringIndex ).isEmpty() )
200  {
201  return;
202  }
203 
204  // negative index removes from end, e.g., -1 removes last one
205  if ( index < 0 )
206  {
207  index = mPoints.at( geometryIndex ).at( ringIndex ).size() + index;
208  }
209  mPoints[geometryIndex][ringIndex].removeAt( index );
210 
211  if ( doUpdate )
212  {
213  updateRect();
214  update();
215  }
216 }
217 
218 void QgsRubberBand::removeLastPoint( int geometryIndex, bool doUpdate/* = true*/, int ringIndex/* = 0*/ )
219 {
220  removePoint( -1, doUpdate, geometryIndex, ringIndex );
221 }
222 
223 void QgsRubberBand::movePoint( const QgsPointXY &p, int geometryIndex, int ringIndex )
224 {
225  if ( geometryIndex < 0 || ringIndex < 0 ||
226  mPoints.size() <= geometryIndex ||
227  mPoints.at( geometryIndex ).size() <= ringIndex ||
228  mPoints.at( geometryIndex ).at( ringIndex ).isEmpty() )
229  {
230  return;
231  }
232 
233  mPoints[geometryIndex][ringIndex].last() = p;
234 
235  updateRect();
236  update();
237 }
238 
239 void QgsRubberBand::movePoint( int index, const QgsPointXY &p, int geometryIndex, int ringIndex )
240 {
241  if ( geometryIndex < 0 || ringIndex < 0 || index < 0 ||
242  mPoints.size() <= geometryIndex ||
243  mPoints.at( geometryIndex ).size() <= ringIndex ||
244  mPoints.at( geometryIndex ).at( ringIndex ).size() <= index )
245  {
246  return;
247  }
248 
249  mPoints[geometryIndex][ringIndex][index] = p;
250 
251  updateRect();
252  update();
253 }
254 
256 {
257  if ( geom.isNull() )
258  {
259  reset( mGeometryType );
260  return;
261  }
262 
263  reset( geom.type() );
264  addGeometry( geom, layer );
265 }
266 
268 {
269  if ( geom.isNull() )
270  {
271  reset( mGeometryType );
272  return;
273  }
274 
275  reset( geom.type() );
276  addGeometry( geom, crs );
277 }
278 
280 {
281  QgsGeometry geom = geometry;
282  if ( layer )
283  {
285  try
286  {
287  geom.transform( ct );
288  }
289  catch ( QgsCsException & )
290  {
291  return;
292  }
293  }
294 
295  addGeometry( geom );
296 }
297 
299 {
300  if ( geometry.isEmpty() )
301  {
302  return;
303  }
304 
305  //maprender object of canvas
306  const QgsMapSettings &ms = mMapCanvas->mapSettings();
307 
308  int idx = mPoints.size();
309 
310  QgsGeometry geom = geometry;
311  if ( crs.isValid() )
312  {
314  geom.transform( ct );
315  }
316 
317  QgsWkbTypes::Type geomType = geom.wkbType();
319  {
320  QgsPointXY pt = geom.asPoint();
321  addPoint( pt, false, idx );
322  removeLastPoint( idx, false );
323  }
324  else if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::PointGeometry && QgsWkbTypes::isMultiType( geomType ) )
325  {
326  const QgsMultiPointXY mpt = geom.asMultiPoint();
327  for ( const QgsPointXY &pt : mpt )
328  {
329  addPoint( pt, false, idx );
330  removeLastPoint( idx, false );
331  idx++;
332  }
333  }
334  else if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::LineGeometry && !QgsWkbTypes::isMultiType( geomType ) )
335  {
336  const QgsPolylineXY line = geom.asPolyline();
337  for ( const QgsPointXY &pt : line )
338  {
339  addPoint( pt, false, idx );
340  }
341  }
342  else if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::LineGeometry && QgsWkbTypes::isMultiType( geomType ) )
343  {
344  const QgsMultiPolylineXY mline = geom.asMultiPolyline();
345  for ( const QgsPolylineXY &line : mline )
346  {
347  if ( line.isEmpty() )
348  {
349  continue;
350  }
351  for ( const QgsPointXY &pt : line )
352  {
353  addPoint( pt, false, idx );
354  }
355  idx++;
356  }
357  }
358  else if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::PolygonGeometry && !QgsWkbTypes::isMultiType( geomType ) )
359  {
360  const QgsPolygonXY poly = geom.asPolygon();
361  int ringIdx = 0;
362  for ( const QgsPolylineXY &ring : poly )
363  {
364  for ( const QgsPointXY &pt : ring )
365  {
366  addPoint( pt, false, idx, ringIdx );
367  }
368  ringIdx++;
369  }
370  }
372  {
373  const QgsMultiPolygonXY multipoly = geom.asMultiPolygon();
374  for ( const QgsPolygonXY &poly : multipoly )
375  {
376  if ( poly.isEmpty() )
377  continue;
378 
379  int ringIdx = 0;
380  for ( const QgsPolylineXY &ring : poly )
381  {
382  for ( const QgsPointXY &pt : ring )
383  {
384  addPoint( pt, false, idx, ringIdx );
385  }
386  ringIdx++;
387  }
388  idx++;
389  }
390  }
391  else
392  {
393  return;
394  }
395 
396  setVisible( true );
397  updateRect();
398  update();
399 }
400 
402 {
403  if ( !mMapCanvas )
404  {
405  return;
406  }
407 
408  const QgsMapToPixel *transform = mMapCanvas->getCoordinateTransform();
409  QgsPointXY ll = transform->toMapCoordinates( rect.left(), rect.bottom() );
410  QgsPointXY lr = transform->toMapCoordinates( rect.right(), rect.bottom() );
411  QgsPointXY ul = transform->toMapCoordinates( rect.left(), rect.top() );
412  QgsPointXY ur = transform->toMapCoordinates( rect.right(), rect.top() );
413 
415  addPoint( ll, false );
416  addPoint( lr, false );
417  addPoint( ur, false );
418  addPoint( ul, true );
419 }
420 
421 void QgsRubberBand::paint( QPainter *p )
422 {
423  if ( mPoints.isEmpty() )
424  return;
425 
426  QVector< QVector<QPolygonF> > shapes;
427  shapes.reserve( mPoints.size() );
428  for ( const QgsPolygonXY &poly : qgis::as_const( mPoints ) )
429  {
430  QVector<QPolygonF> rings;
431  rings.reserve( poly.size() );
432  for ( const QgsPolylineXY &line : poly )
433  {
434  QVector<QPointF> pts;
435  pts.reserve( line.size() );
436  for ( const QgsPointXY &pt : line )
437  {
438  const QPointF cur = toCanvasCoordinates( QgsPointXY( pt.x() + mTranslationOffsetX, pt.y() + mTranslationOffsetY ) ) - pos();
439  if ( pts.isEmpty() || std::abs( pts.last().x() - cur.x() ) > 1 || std::abs( pts.last().y() - cur.y() ) > 1 )
440  pts.append( cur );
441  }
442  rings.append( pts );
443  }
444  shapes.append( rings );
445  }
446 
447  int iterations = mSecondaryPen.color().isValid() ? 2 : 1;
448  for ( int i = 0; i < iterations; ++i )
449  {
450  if ( i == 0 && iterations > 1 )
451  {
452  // first iteration with multi-pen painting, so use secondary pen
453  mSecondaryPen.setWidth( mPen.width() + 2 );
454  p->setBrush( Qt::NoBrush );
455  p->setPen( mSecondaryPen );
456  }
457  else
458  {
459  // "top" layer, use primary pen/brush
460  p->setBrush( mBrush );
461  p->setPen( mPen );
462  }
463 
464  for ( const QVector<QPolygonF> &shape : qgis::as_const( shapes ) )
465  {
466  drawShape( p, shape );
467  }
468  }
469 }
470 
471 void QgsRubberBand::drawShape( QPainter *p, const QVector<QPolygonF> &rings )
472 {
473  if ( rings.size() == 1 )
474  {
475  drawShape( p, rings.at( 0 ) );
476  }
477  else
478  {
479  QPainterPath path;
480  for ( const QPolygonF &poly : rings )
481  {
482  path.addPolygon( poly );
483  }
484  p->drawPath( path );
485  }
486 }
487 
488 void QgsRubberBand::drawShape( QPainter *p, const QVector<QPointF> &pts )
489 {
490  switch ( mGeometryType )
491  {
493  {
494  p->drawPolygon( pts );
495  }
496  break;
497 
499  {
500  const auto constPts = pts;
501  for ( QPointF pt : constPts )
502  {
503  double x = pt.x();
504  double y = pt.y();
505 
506  qreal s = ( mIconSize - 1 ) / 2.0;
507 
508  switch ( mIconType )
509  {
510  case ICON_NONE:
511  break;
512 
513  case ICON_CROSS:
514  p->drawLine( QLineF( x - s, y, x + s, y ) );
515  p->drawLine( QLineF( x, y - s, x, y + s ) );
516  break;
517 
518  case ICON_X:
519  p->drawLine( QLineF( x - s, y - s, x + s, y + s ) );
520  p->drawLine( QLineF( x - s, y + s, x + s, y - s ) );
521  break;
522 
523  case ICON_BOX:
524  p->drawLine( QLineF( x - s, y - s, x + s, y - s ) );
525  p->drawLine( QLineF( x + s, y - s, x + s, y + s ) );
526  p->drawLine( QLineF( x + s, y + s, x - s, y + s ) );
527  p->drawLine( QLineF( x - s, y + s, x - s, y - s ) );
528  break;
529 
530  case ICON_FULL_BOX:
531  p->drawRect( static_cast< int>( x - s ), static_cast< int >( y - s ), mIconSize, mIconSize );
532  break;
533 
534  case ICON_CIRCLE:
535  p->drawEllipse( static_cast< int >( x - s ), static_cast< int >( y - s ), mIconSize, mIconSize );
536  break;
537 
538  case ICON_DIAMOND:
539  case ICON_FULL_DIAMOND:
540  {
541  QPointF pts[] =
542  {
543  QPointF( x, y - s ),
544  QPointF( x + s, y ),
545  QPointF( x, y + s ),
546  QPointF( x - s, y )
547  };
548  if ( mIconType == ICON_FULL_DIAMOND )
549  p->drawPolygon( pts, 4 );
550  else
551  p->drawPolyline( pts, 4 );
552  break;
553  }
554 
555  case ICON_SVG:
556  {
557  QRectF viewBox = mSvgRenderer->viewBoxF();
558  QRectF r( mSvgOffset.x(), mSvgOffset.y(), viewBox.width(), viewBox.height() );
559  QgsScopedQPainterState painterState( p );
560  p->translate( pt );
561  mSvgRenderer->render( p, r );
562  break;
563  }
564  }
565  }
566  }
567  break;
568 
570  default:
571  {
572  p->drawPolyline( pts );
573  }
574  break;
575  }
576 }
577 
579 {
580  if ( mPoints.isEmpty() )
581  {
582  setRect( QgsRectangle() );
583  setVisible( false );
584  return;
585  }
586 
587  const QgsMapToPixel &m2p = *( mMapCanvas->getCoordinateTransform() );
588 
589 #if 0 // unused?
590  double iconSize = ( mIconSize + 1 ) / 2.;
591  if ( mSvgRenderer )
592  {
593  QRectF viewBox = mSvgRenderer->viewBoxF();
594  iconSize = std::max( std::fabs( mSvgOffset.x() ) + .5 * viewBox.width(), std::fabs( mSvgOffset.y() ) + .5 * viewBox.height() );
595  }
596 #endif
597 
598  qreal w = ( ( mIconSize - 1 ) / 2 + mPen.width() ); // in canvas units
599 
600  QgsRectangle r; // in canvas units
601  for ( const QgsPolygonXY &poly : qgis::as_const( mPoints ) )
602  {
603  for ( const QgsPointXY &point : poly.at( 0 ) )
604  {
605  QgsPointXY p( point.x() + mTranslationOffsetX, point.y() + mTranslationOffsetY );
606  p = m2p.transform( p );
607  QgsRectangle rect( p.x() - w, p.y() - w, p.x() + w, p.y() + w );
608 
609  if ( r.isEmpty() )
610  {
611  // Get rectangle of the first point
612  r = rect;
613  }
614  else
615  {
616  r.combineExtentWith( rect );
617  }
618  }
619  }
620 
621  // This is an hack to pass QgsMapCanvasItem::setRect what it
622  // expects (encoding of position and size of the item)
623  qreal res = m2p.mapUnitsPerPixel();
624  QgsPointXY topLeft = m2p.toMapCoordinates( r.xMinimum(), r.yMinimum() );
625  QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + r.width()*res, topLeft.y() - r.height()*res );
626 
627  setRect( rect );
628 }
629 
631 {
632  // re-compute rectangle
633  // See https://github.com/qgis/QGIS/issues/20566
634  // NOTE: could be optimized by saving map-extent
635  // of rubberband and simply re-projecting
636  // that to device-rectangle on "updatePosition"
637  updateRect();
638 }
639 
640 void QgsRubberBand::setTranslationOffset( double dx, double dy )
641 {
642  mTranslationOffsetX = dx;
643  mTranslationOffsetY = dy;
644  updateRect();
645 }
646 
648 {
649  return mPoints.size();
650 }
651 
652 int QgsRubberBand::partSize( int geometryIndex ) const
653 {
654  if ( geometryIndex < 0 ||
655  geometryIndex >= mPoints.size() ||
656  mPoints.at( geometryIndex ).isEmpty() )
657  return 0;
658  return mPoints.at( geometryIndex ).at( 0 ).size();
659 }
660 
662 {
663  int count = 0;
664  for ( const QgsPolygonXY &poly : qgis::as_const( mPoints ) )
665  {
666  for ( const QgsPolylineXY &ring : poly )
667  {
668  count += ring.size();
669  }
670  }
671  return count;
672 }
673 
674 const QgsPointXY *QgsRubberBand::getPoint( int i, int j, int ringIndex ) const
675 {
676  if ( i < 0 || ringIndex < 0 || j < 0 ||
677  mPoints.size() <= i ||
678  mPoints.at( i ).size() <= ringIndex ||
679  mPoints.at( i ).at( ringIndex ).size() <= j )
680  return nullptr;
681  else
682  return &mPoints[i][ringIndex][j];
683 }
684 
686 {
687  QgsGeometry geom;
688 
689  switch ( mGeometryType )
690  {
692  {
693  geom = QgsGeometry::fromMultiPolygonXY( mPoints );
694  break;
695  }
696 
698  {
699  QgsMultiPointXY multiPoint;
700 
701  for ( const QgsPolygonXY &poly : qgis::as_const( mPoints ) )
702  {
703  if ( poly.isEmpty() )
704  continue;
705  multiPoint.append( poly.at( 0 ) );
706  }
707  geom = QgsGeometry::fromMultiPointXY( multiPoint );
708  break;
709  }
710 
712  default:
713  {
714  if ( !mPoints.isEmpty() )
715  {
716  if ( mPoints.size() > 1 )
717  {
718  QgsMultiPolylineXY multiPolyline;
719  for ( const QgsPolygonXY &poly : qgis::as_const( mPoints ) )
720  {
721  if ( poly.isEmpty() )
722  continue;
723  multiPolyline.append( poly.at( 0 ) );
724  }
725  geom = QgsGeometry::fromMultiPolylineXY( multiPolyline );
726  }
727  else
728  {
729  if ( !mPoints.at( 0 ).isEmpty() )
730  geom = QgsGeometry::fromPolylineXY( mPoints.at( 0 ).at( 0 ) );
731  else
733  }
734  }
735  break;
736  }
737  }
738  return geom;
739 }
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
A cross is used to highlight points (x)
Definition: qgsrubberband.h:90
void setIconSize(int iconSize)
Sets the size of the point icons.
static QgsGeometry fromMultiPolygonXY(const QgsMultiPolygonXY &multipoly)
Creates a new geometry from a QgsMultiPolygon.
void setWidth(int width)
Sets the width of the line.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
int numberOfVertices() const
Returns count of vertices in all lists of mPoint.
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
void addPoint(const QgsPointXY &p, bool doUpdate=true, int geometryIndex=0, int ringIndex=0)
Adds a vertex to the rubberband and update canvas.
QgsRectangle rect() const
returns canvas item rectangle in map units
void setToCanvasRectangle(QRect rect)
Sets this rubber band to a map canvas rectangle.
void setStrokeColor(const QColor &color)
Sets the stroke color for the rubberband.
IconType icon() const
Returns the current icon type to highlight point geometries.
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
void setTranslationOffset(double dx, double dy)
Adds translation to original coordinates (all in map coordinates)
void setLineStyle(Qt::PenStyle penStyle)
Sets the style of the line.
double y
Definition: qgspointxy.h:48
A class to represent a 2D point.
Definition: qgspointxy.h:43
static QgsGeometry fromMultiPolylineXY(const QgsMultiPolylineXY &multiline)
Creates a new geometry from a QgsMultiPolylineXY object.
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item...
Definition: qgsgeometry.h:75
An abstract class for items that can be placed on the map canvas.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:123
void setSecondaryStrokeColor(const QColor &color)
Sets a secondary stroke color for the rubberband which will be drawn under the main stroke color...
A diamond is used to highlight points (◇)
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
Definition: qgsgeometry.h:81
void updatePosition() override
called on changed extent or resize event to update position of the item
void addGeometry(const QgsGeometry &geometry, QgsVectorLayer *layer)
Adds the geometry of an existing feature to a rubberband This is useful for multi feature highlightin...
const QgsCoordinateReferenceSystem & crs
A cross is used to highlight points (+)
Definition: qgsrubberband.h:85
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:84
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
Definition: qgsgeometry.h:92
void paint(QPainter *p) override
Paints the rubber band in response to an update event.
QgsCoordinateReferenceSystem destinationCrs() const
returns CRS of destination coordinate reference system
int width() const
Returns the current width of the line or stroke width for polygon.
The QgsMapSettings class contains configuration for rendering of the map.
void setToGeometry(const QgsGeometry &geom, QgsVectorLayer *layer)
Sets this rubber band to geom.
QgsRubberBand(QgsMapCanvas *mapCanvas, QgsWkbTypes::GeometryType geometryType=QgsWkbTypes::LineGeometry)
Creates a new RubberBand.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:85
QgsMultiPolylineXY asMultiPolyline() const
Returns the contents of the geometry as a multi-linestring.
QgsCoordinateTransform layerTransform(const QgsMapLayer *layer) const
Returns the coordinate transform from layer&#39;s CRS to destination CRS.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:37
QgsPointXY transform(const QgsPointXY &p) const
Transform the point from map (world) coordinates to device coordinates.
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
Scoped object for saving and restoring a QPainter object&#39;s state.
void setSvgIcon(const QString &path, QPoint drawOffset)
Set the path to the svg file to use to draw points.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:69
An svg image is used to highlight points.
QgsGeometry asGeometry() const
Returns the rubberband as a Geometry.
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:437
A circle is used to highlight points (○)
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.
void setRect(const QgsRectangle &r, bool resetRotation=true)
sets canvas item rectangle in map units
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
void setFillColor(const QColor &color)
Sets the fill color for the rubberband.
double mapUnitsPerPixel() const
Returns current map units per pixel.
double x
Definition: qgspointxy.h:47
QgsMapCanvasItem(QgsMapCanvas *mapCanvas)
protected constructor: cannot be constructed directly
void setBrushStyle(Qt::BrushStyle brushStyle)
Sets the style of the brush.
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...
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle...
Definition: qgsrectangle.h:359
void setIcon(IconType icon)
Sets the icon type to highlight point geometries.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:140
A box is used to highlight points (□)
Definition: qgsrubberband.h:95
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Definition: qgsgeometry.h:51
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
const QgsPointXY * getPoint(int i, int j=0, int ringIndex=0) const
Returns a vertex.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
void removePoint(int index=0, bool doUpdate=true, int geometryIndex=0, int ringIndex=0)
Removes a vertex from the rubberband and (optionally) updates canvas.
int iconSize() const
Returns the current icon size of the point icons.
void drawShape(QPainter *p, const QVector< QPointF > &pts)
Draws shape of the rubber band.
int partSize(int geometryIndex) const
Returns number of vertices in feature part.
QgsMapCanvas * mMapCanvas
pointer to map canvas
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:468
This class represents a coordinate reference system (CRS).
void movePoint(const QgsPointXY &p, int geometryIndex=0, int ringIndex=0)
Moves the rubber band point specified by index.
A diamond is used to highlight points (◆)
Class for doing transforms between two map coordinate systems.
const QgsMapToPixel * getCoordinateTransform()
Gets the current coordinate transform.
void reset(QgsWkbTypes::GeometryType geometryType=QgsWkbTypes::LineGeometry)
Clears all the geometries in this rubberband.
void removeLastPoint(int geometryIndex=0, bool doUpdate=true, int ringIndex=0)
Removes the last point.
void setColor(const QColor &color)
Sets the color for the rubberband.
QgsPolylineXY asPolyline() const
Returns the contents of the geometry as a polyline.
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
Definition: qgswkbtypes.h:832
No icon is used.
Definition: qgsrubberband.h:80
QgsMultiPointXY asMultiPoint() const
Returns the contents of the geometry as a multi-point.
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:127
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
int size() const
Returns number of geometries.
QPointF toCanvasCoordinates(const QgsPointXY &point) const
transformation from map coordinates to screen coordinates
Represents a vector layer which manages a vector based data sets.
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
QgsPointXY toMapCoordinates(int x, int y) const
Transform device coordinates to map (world) coordinates.
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:938
void updateRect()
Recalculates needed rectangle.
A full box is used to highlight points (■)
bool isValid() const
Returns whether this CRS is correctly initialized and usable.