QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
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 
40 QgsRubberBand::QgsRubberBand()
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 
70 void QgsRubberBand::setWidth( int width )
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 
279 void QgsRubberBand::addGeometry( const QgsGeometry &geometry, QgsVectorLayer *layer, bool doUpdate )
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, QgsCoordinateReferenceSystem(), doUpdate );
296 }
297 
298 void QgsRubberBand::addGeometry( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &crs, bool doUpdate )
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  try
315  {
316  geom.transform( ct );
317  }
318  catch ( QgsCsException & )
319  {
320  QgsDebugMsg( QStringLiteral( "Could not transform rubber band geometry to map CRS" ) );
321  return;
322  }
323  }
324 
325  QgsWkbTypes::Type geomType = geom.wkbType();
327  {
328  QgsPointXY pt = geom.asPoint();
329  addPoint( pt, false, idx );
330  removeLastPoint( idx, false );
331  }
332  else if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::PointGeometry && QgsWkbTypes::isMultiType( geomType ) )
333  {
334  const QgsMultiPointXY mpt = geom.asMultiPoint();
335  for ( const QgsPointXY &pt : mpt )
336  {
337  addPoint( pt, false, idx );
338  removeLastPoint( idx, false );
339  idx++;
340  }
341  }
342  else if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::LineGeometry && !QgsWkbTypes::isMultiType( geomType ) )
343  {
344  const QgsPolylineXY line = geom.asPolyline();
345  for ( const QgsPointXY &pt : line )
346  {
347  addPoint( pt, false, idx );
348  }
349  }
350  else if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::LineGeometry && QgsWkbTypes::isMultiType( geomType ) )
351  {
352  const QgsMultiPolylineXY mline = geom.asMultiPolyline();
353  for ( const QgsPolylineXY &line : mline )
354  {
355  if ( line.isEmpty() )
356  {
357  continue;
358  }
359  for ( const QgsPointXY &pt : line )
360  {
361  addPoint( pt, false, idx );
362  }
363  idx++;
364  }
365  }
366  else if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::PolygonGeometry && !QgsWkbTypes::isMultiType( geomType ) )
367  {
368  const QgsPolygonXY poly = geom.asPolygon();
369  int ringIdx = 0;
370  for ( const QgsPolylineXY &ring : poly )
371  {
372  for ( const QgsPointXY &pt : ring )
373  {
374  addPoint( pt, false, idx, ringIdx );
375  }
376  ringIdx++;
377  }
378  }
380  {
381  const QgsMultiPolygonXY multipoly = geom.asMultiPolygon();
382  for ( const QgsPolygonXY &poly : multipoly )
383  {
384  if ( poly.isEmpty() )
385  continue;
386 
387  int ringIdx = 0;
388  for ( const QgsPolylineXY &ring : poly )
389  {
390  for ( const QgsPointXY &pt : ring )
391  {
392  addPoint( pt, false, idx, ringIdx );
393  }
394  ringIdx++;
395  }
396  idx++;
397  }
398  }
399  else
400  {
401  return;
402  }
403 
404  setVisible( true );
405  if ( doUpdate )
406  {
407  updateRect();
408  update();
409  }
410 }
411 
413 {
414  if ( !mMapCanvas )
415  {
416  return;
417  }
418 
419  const QgsMapToPixel *transform = mMapCanvas->getCoordinateTransform();
420  QgsPointXY ll = transform->toMapCoordinates( rect.left(), rect.bottom() );
421  QgsPointXY lr = transform->toMapCoordinates( rect.right(), rect.bottom() );
422  QgsPointXY ul = transform->toMapCoordinates( rect.left(), rect.top() );
423  QgsPointXY ur = transform->toMapCoordinates( rect.right(), rect.top() );
424 
426  addPoint( ll, false );
427  addPoint( lr, false );
428  addPoint( ur, false );
429  addPoint( ul, true );
430 }
431 
432 void QgsRubberBand::paint( QPainter *p )
433 {
434  if ( mPoints.isEmpty() )
435  return;
436 
437  QVector< QVector<QPolygonF> > shapes;
438  shapes.reserve( mPoints.size() );
439  for ( const QgsPolygonXY &poly : qgis::as_const( mPoints ) )
440  {
441  QVector<QPolygonF> rings;
442  rings.reserve( poly.size() );
443  for ( const QgsPolylineXY &line : poly )
444  {
445  QVector<QPointF> pts;
446  pts.reserve( line.size() );
447  for ( const QgsPointXY &pt : line )
448  {
449  const QPointF cur = toCanvasCoordinates( QgsPointXY( pt.x() + mTranslationOffsetX, pt.y() + mTranslationOffsetY ) ) - pos();
450  if ( pts.isEmpty() || std::abs( pts.last().x() - cur.x() ) > 1 || std::abs( pts.last().y() - cur.y() ) > 1 )
451  pts.append( cur );
452  }
453  rings.append( pts );
454  }
455  shapes.append( rings );
456  }
457 
458  int iterations = mSecondaryPen.color().isValid() ? 2 : 1;
459  for ( int i = 0; i < iterations; ++i )
460  {
461  if ( i == 0 && iterations > 1 )
462  {
463  // first iteration with multi-pen painting, so use secondary pen
464  mSecondaryPen.setWidth( mPen.width() + 2 );
465  p->setBrush( Qt::NoBrush );
466  p->setPen( mSecondaryPen );
467  }
468  else
469  {
470  // "top" layer, use primary pen/brush
471  p->setBrush( mBrush );
472  p->setPen( mPen );
473  }
474 
475  for ( const QVector<QPolygonF> &shape : qgis::as_const( shapes ) )
476  {
477  drawShape( p, shape );
478  }
479  }
480 }
481 
482 void QgsRubberBand::drawShape( QPainter *p, const QVector<QPolygonF> &rings )
483 {
484  if ( rings.size() == 1 )
485  {
486  drawShape( p, rings.at( 0 ) );
487  }
488  else
489  {
490  QPainterPath path;
491  for ( const QPolygonF &poly : rings )
492  {
493  path.addPolygon( poly );
494  }
495  p->drawPath( path );
496  }
497 }
498 
499 void QgsRubberBand::drawShape( QPainter *p, const QVector<QPointF> &pts )
500 {
501  switch ( mGeometryType )
502  {
504  {
505  p->drawPolygon( pts );
506  }
507  break;
508 
510  {
511  const auto constPts = pts;
512  for ( QPointF pt : constPts )
513  {
514  double x = pt.x();
515  double y = pt.y();
516 
517  qreal s = ( mIconSize - 1 ) / 2.0;
518 
519  switch ( mIconType )
520  {
521  case ICON_NONE:
522  break;
523 
524  case ICON_CROSS:
525  p->drawLine( QLineF( x - s, y, x + s, y ) );
526  p->drawLine( QLineF( x, y - s, x, y + s ) );
527  break;
528 
529  case ICON_X:
530  p->drawLine( QLineF( x - s, y - s, x + s, y + s ) );
531  p->drawLine( QLineF( x - s, y + s, x + s, y - s ) );
532  break;
533 
534  case ICON_BOX:
535  p->drawLine( QLineF( x - s, y - s, x + s, y - s ) );
536  p->drawLine( QLineF( x + s, y - s, x + s, y + s ) );
537  p->drawLine( QLineF( x + s, y + s, x - s, y + s ) );
538  p->drawLine( QLineF( x - s, y + s, x - s, y - s ) );
539  break;
540 
541  case ICON_FULL_BOX:
542  p->drawRect( static_cast< int>( x - s ), static_cast< int >( y - s ), mIconSize, mIconSize );
543  break;
544 
545  case ICON_CIRCLE:
546  p->drawEllipse( static_cast< int >( x - s ), static_cast< int >( y - s ), mIconSize, mIconSize );
547  break;
548 
549  case ICON_DIAMOND:
550  case ICON_FULL_DIAMOND:
551  {
552  QPointF pts[] =
553  {
554  QPointF( x, y - s ),
555  QPointF( x + s, y ),
556  QPointF( x, y + s ),
557  QPointF( x - s, y )
558  };
559  if ( mIconType == ICON_FULL_DIAMOND )
560  p->drawPolygon( pts, 4 );
561  else
562  p->drawPolyline( pts, 4 );
563  break;
564  }
565 
566  case ICON_SVG:
567  {
568  QRectF viewBox = mSvgRenderer->viewBoxF();
569  QRectF r( mSvgOffset.x(), mSvgOffset.y(), viewBox.width(), viewBox.height() );
570  QgsScopedQPainterState painterState( p );
571  p->translate( pt );
572  mSvgRenderer->render( p, r );
573  break;
574  }
575  }
576  }
577  }
578  break;
579 
581  default:
582  {
583  p->drawPolyline( pts );
584  }
585  break;
586  }
587 }
588 
590 {
591  if ( mPoints.isEmpty() )
592  {
593  setRect( QgsRectangle() );
594  setVisible( false );
595  return;
596  }
597 
598  const QgsMapToPixel &m2p = *( mMapCanvas->getCoordinateTransform() );
599 
600 #if 0 // unused?
601  double iconSize = ( mIconSize + 1 ) / 2.;
602  if ( mSvgRenderer )
603  {
604  QRectF viewBox = mSvgRenderer->viewBoxF();
605  iconSize = std::max( std::fabs( mSvgOffset.x() ) + .5 * viewBox.width(), std::fabs( mSvgOffset.y() ) + .5 * viewBox.height() );
606  }
607 #endif
608 
609  qreal w = ( ( mIconSize - 1 ) / 2 + mPen.width() ); // in canvas units
610 
611  QgsRectangle r; // in canvas units
612  for ( const QgsPolygonXY &poly : qgis::as_const( mPoints ) )
613  {
614  for ( const QgsPointXY &point : poly.at( 0 ) )
615  {
616  QgsPointXY p( point.x() + mTranslationOffsetX, point.y() + mTranslationOffsetY );
617  p = m2p.transform( p );
618  QgsRectangle rect( p.x() - w, p.y() - w, p.x() + w, p.y() + w );
619 
620  if ( r.isEmpty() )
621  {
622  // Get rectangle of the first point
623  r = rect;
624  }
625  else
626  {
627  r.combineExtentWith( rect );
628  }
629  }
630  }
631 
632  // This is an hack to pass QgsMapCanvasItem::setRect what it
633  // expects (encoding of position and size of the item)
634  qreal res = m2p.mapUnitsPerPixel();
635  QgsPointXY topLeft = m2p.toMapCoordinates( r.xMinimum(), r.yMinimum() );
636  QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + r.width()*res, topLeft.y() - r.height()*res );
637 
638  setRect( rect );
639 }
640 
642 {
643  // re-compute rectangle
644  // See https://github.com/qgis/QGIS/issues/20566
645  // NOTE: could be optimized by saving map-extent
646  // of rubberband and simply re-projecting
647  // that to device-rectangle on "updatePosition"
648  updateRect();
649 }
650 
651 void QgsRubberBand::setTranslationOffset( double dx, double dy )
652 {
653  mTranslationOffsetX = dx;
654  mTranslationOffsetY = dy;
655  updateRect();
656 }
657 
659 {
660  return mPoints.size();
661 }
662 
663 int QgsRubberBand::partSize( int geometryIndex ) const
664 {
665  if ( geometryIndex < 0 ||
666  geometryIndex >= mPoints.size() ||
667  mPoints.at( geometryIndex ).isEmpty() )
668  return 0;
669  return mPoints.at( geometryIndex ).at( 0 ).size();
670 }
671 
673 {
674  int count = 0;
675  for ( const QgsPolygonXY &poly : qgis::as_const( mPoints ) )
676  {
677  for ( const QgsPolylineXY &ring : poly )
678  {
679  count += ring.size();
680  }
681  }
682  return count;
683 }
684 
685 const QgsPointXY *QgsRubberBand::getPoint( int i, int j, int ringIndex ) const
686 {
687  if ( i < 0 || ringIndex < 0 || j < 0 ||
688  mPoints.size() <= i ||
689  mPoints.at( i ).size() <= ringIndex ||
690  mPoints.at( i ).at( ringIndex ).size() <= j )
691  return nullptr;
692  else
693  return &mPoints[i][ringIndex][j];
694 }
695 
697 {
698  QgsGeometry geom;
699 
700  switch ( mGeometryType )
701  {
703  {
704  geom = QgsGeometry::fromMultiPolygonXY( mPoints );
705  break;
706  }
707 
709  {
710  QgsMultiPointXY multiPoint;
711 
712  for ( const QgsPolygonXY &poly : qgis::as_const( mPoints ) )
713  {
714  if ( poly.isEmpty() )
715  continue;
716  multiPoint.append( poly.at( 0 ) );
717  }
718  geom = QgsGeometry::fromMultiPointXY( multiPoint );
719  break;
720  }
721 
723  default:
724  {
725  if ( !mPoints.isEmpty() )
726  {
727  if ( mPoints.size() > 1 )
728  {
729  QgsMultiPolylineXY multiPolyline;
730  for ( const QgsPolygonXY &poly : qgis::as_const( mPoints ) )
731  {
732  if ( poly.isEmpty() )
733  continue;
734  multiPolyline.append( poly.at( 0 ) );
735  }
736  geom = QgsGeometry::fromMultiPolylineXY( multiPolyline );
737  }
738  else
739  {
740  if ( !mPoints.at( 0 ).isEmpty() )
741  geom = QgsGeometry::fromPolylineXY( mPoints.at( 0 ).at( 0 ) );
742  else
744  }
745  }
746  break;
747  }
748  }
749  return geom;
750 }
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Class for doing transforms between two map coordinate systems.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsMultiPolygonXY asMultiPolygon() const
Returns the contents of the geometry as a multi-polygon.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static QgsGeometry fromMultiPolylineXY(const QgsMultiPolylineXY &multiline)
Creates a new geometry from a QgsMultiPolylineXY object.
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.
Q_GADGET bool isNull
Definition: qgsgeometry.h:126
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.
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:127
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 QgsMultiPolygon.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
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.
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:86
const QgsMapToPixel * getCoordinateTransform()
Gets the current coordinate transform.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
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.
Definition: qgsmaptopixel.h:39
double mapUnitsPerPixel() const
Returns current map units per pixel.
QgsPointXY toMapCoordinates(int x, int y) const
Transform device coordinates to map (world) coordinates.
QgsPointXY transform(const QgsPointXY &p) const
Transform the point p from map (world) coordinates to device coordinates.
Definition: qgsmaptopixel.h:82
A class to represent a 2D point.
Definition: qgspointxy.h:44
double y
Definition: qgspointxy.h:48
Q_GADGET double x
Definition: qgspointxy.h:47
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:501
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
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 combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:359
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:437
QgsRubberBand(QgsMapCanvas *mapCanvas, QgsWkbTypes::GeometryType geometryType=QgsWkbTypes::LineGeometry)
Creates a new RubberBand.
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.
void setWidth(int width)
Sets the width of the line.
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.
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 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)
Definition: qgsrubberband.h:90
@ 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.
Definition: qgsrubberband.h:80
@ ICON_CROSS
A cross is used to highlight points (+)
Definition: qgsrubberband.h:85
@ 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 (□)
Definition: qgsrubberband.h:95
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.
void setIconSize(int iconSize)
Sets the size of the point icons.
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 addGeometry(const QgsGeometry &geometry, QgsVectorLayer *layer, bool doUpdate=true)
Adds the geometry of an existing feature to a rubberband This is useful for multi feature highlightin...
void reset(QgsWkbTypes::GeometryType geometryType=QgsWkbTypes::LineGeometry)
Clears all the geometries in this rubberband.
void updatePosition() override
called on changed extent or resize event to update position of the item
int numberOfVertices() const
Returns count of vertices in all lists of mPoint.
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.
Represents a vector layer which manages a vector based data sets.
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
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
Definition: qgswkbtypes.h:832
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:141
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
Definition: qgsgeometry.h:75
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:85
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
Definition: qgsgeometry.h:81
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Definition: qgsgeometry.h:51
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
Definition: qgsgeometry.h:92
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
const QgsCoordinateReferenceSystem & crs