QGIS API Documentation 3.37.0-Master (684a802617f)
Loading...
Searching...
No Matches
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 "qgssymbol.h"
24#include "qgsrendercontext.h"
25#include "qgslinesymbol.h"
26#include "qgsfillsymbol.h"
27#include "qgsguiutils.h"
28
29#include <QPainter>
30
32 : QObject( nullptr )
33 , QgsMapCanvasItem( mapCanvas )
34 , mGeometryType( geometryType )
35{
36 reset( geometryType );
37 QColor color( Qt::lightGray );
38 color.setAlpha( 63 );
39 setColor( color );
40 setWidth( 1 );
41 setLineStyle( Qt::SolidLine );
42 setBrushStyle( Qt::SolidPattern );
43 setSecondaryStrokeColor( QColor() );
44}
45
46QgsRubberBand::QgsRubberBand()
47 : QObject( nullptr )
48 , QgsMapCanvasItem( nullptr )
49{
50}
51
53
54void QgsRubberBand::setColor( const QColor &color )
55{
56 setStrokeColor( color );
57 setFillColor( color );
58}
59
60void QgsRubberBand::setFillColor( const QColor &color )
61{
62 if ( mBrush.color() == color )
63 return;
64
65 mBrush.setColor( color );
66}
67
68void QgsRubberBand::setStrokeColor( const QColor &color )
69{
70 mPen.setColor( color );
71}
72
73void QgsRubberBand::setSecondaryStrokeColor( const QColor &color )
74{
75 mSecondaryPen.setColor( color );
76}
77
78void QgsRubberBand::setWidth( int width )
79{
80 mPen.setWidth( width );
81}
82
84{
85 mIconType = icon;
86}
87
88void QgsRubberBand::setSvgIcon( const QString &path, QPoint drawOffset )
89{
91 mSvgRenderer = std::make_unique<QSvgRenderer>( path );
92 mSvgOffset = drawOffset;
93}
94
95void QgsRubberBand::setIconSize( int iconSize )
96{
97 mIconSize = iconSize;
98}
99
100void QgsRubberBand::setLineStyle( Qt::PenStyle penStyle )
101{
102 mPen.setStyle( penStyle );
103}
104
105void QgsRubberBand::setBrushStyle( Qt::BrushStyle brushStyle )
106{
107 mBrush.setStyle( brushStyle );
108}
109
111{
112 mPoints.clear();
113 mGeometryType = geometryType;
114 updateRect();
115 update();
116}
117
118void QgsRubberBand::addPoint( const QgsPointXY &p, bool doUpdate /* = true */, int geometryIndex, int ringIndex )
119{
120 if ( geometryIndex < 0 )
121 {
122 geometryIndex = mPoints.size() - 1;
123 }
124
125 if ( geometryIndex < 0 || geometryIndex > mPoints.size() )
126 {
127 return;
128 }
129
130 if ( geometryIndex == mPoints.size() )
131 {
132 // since we're adding a geometry, ringIndex must be 0 or negative for last ring
133 if ( ringIndex > 0 )
134 return;
135 mPoints.append( QgsPolygonXY() );
136 }
137
138 // negative ringIndex means last ring
139 if ( ringIndex < 0 )
140 {
141 if ( mPoints.at( geometryIndex ).isEmpty() )
142 ringIndex = 0;
143 else
144 ringIndex = mPoints.at( geometryIndex ).size() - 1;
145 }
146
147 if ( ringIndex > mPoints.at( geometryIndex ).size() )
148 return;
149
150 if ( ringIndex == mPoints.at( geometryIndex ).size() )
151 {
152 mPoints[geometryIndex].append( QgsPolylineXY() );
153 if ( mGeometryType != Qgis::GeometryType::Point )
154 mPoints[geometryIndex][ringIndex].append( p );
155 }
156
157 if ( mPoints.at( geometryIndex ).at( ringIndex ).size() == 2 &&
158 mPoints.at( geometryIndex ).at( ringIndex ).at( 0 ) == mPoints.at( geometryIndex ).at( ringIndex ).at( 1 ) )
159 {
160 mPoints[geometryIndex][ringIndex].last() = p;
161 }
162 else
163 {
164 mPoints[geometryIndex][ringIndex].append( p );
165 }
166
167
168 if ( doUpdate )
169 {
170 setVisible( true );
171 updateRect();
172 update();
173 }
174}
175
176void QgsRubberBand::closePoints( bool doUpdate, int geometryIndex, int ringIndex )
177{
178 if ( geometryIndex < 0 || ringIndex < 0 ||
179 mPoints.size() <= geometryIndex ||
180 mPoints.at( geometryIndex ).size() <= ringIndex ||
181 mPoints.at( geometryIndex ).at( ringIndex ).isEmpty() )
182 {
183 return;
184 }
185
186 if ( mPoints.at( geometryIndex ).at( ringIndex ).constFirst() != mPoints.at( geometryIndex ).at( ringIndex ).constLast() )
187 {
188 mPoints[geometryIndex][ringIndex].append( mPoints.at( geometryIndex ).at( ringIndex ).constFirst() );
189 }
190
191 if ( doUpdate )
192 {
193 setVisible( true );
194 updateRect();
195 update();
196 }
197}
198
199
200void QgsRubberBand::removePoint( int index, bool doUpdate/* = true*/, int geometryIndex/* = 0*/, int ringIndex/* = 0*/ )
201{
202
203 if ( geometryIndex < 0 || ringIndex < 0 ||
204 mPoints.size() <= geometryIndex ||
205 mPoints.at( geometryIndex ).size() <= ringIndex ||
206 mPoints.at( geometryIndex ).at( ringIndex ).size() <= index ||
207 mPoints.at( geometryIndex ).at( ringIndex ).size() < -index ||
208 mPoints.at( geometryIndex ).at( ringIndex ).isEmpty() )
209 {
210 return;
211 }
212
213 // negative index removes from end, e.g., -1 removes last one
214 if ( index < 0 )
215 {
216 index = mPoints.at( geometryIndex ).at( ringIndex ).size() + index;
217 }
218 mPoints[geometryIndex][ringIndex].removeAt( index );
219
220 if ( doUpdate )
221 {
222 updateRect();
223 update();
224 }
225}
226
227void QgsRubberBand::removeLastPoint( int geometryIndex, bool doUpdate/* = true*/, int ringIndex/* = 0*/ )
228{
229 removePoint( -1, doUpdate, geometryIndex, ringIndex );
230}
231
232void QgsRubberBand::movePoint( const QgsPointXY &p, int geometryIndex, int ringIndex )
233{
234 if ( geometryIndex < 0 || ringIndex < 0 ||
235 mPoints.size() <= geometryIndex ||
236 mPoints.at( geometryIndex ).size() <= ringIndex ||
237 mPoints.at( geometryIndex ).at( ringIndex ).isEmpty() )
238 {
239 return;
240 }
241
242 mPoints[geometryIndex][ringIndex].last() = p;
243
244 updateRect();
245 update();
246}
247
248void QgsRubberBand::movePoint( int index, const QgsPointXY &p, int geometryIndex, int ringIndex )
249{
250 if ( geometryIndex < 0 || ringIndex < 0 || index < 0 ||
251 mPoints.size() <= geometryIndex ||
252 mPoints.at( geometryIndex ).size() <= ringIndex ||
253 mPoints.at( geometryIndex ).at( ringIndex ).size() <= index )
254 {
255 return;
256 }
257
258 mPoints[geometryIndex][ringIndex][index] = p;
259
260 updateRect();
261 update();
262}
263
265{
266 if ( geom.isNull() )
267 {
268 reset( mGeometryType );
269 return;
270 }
271
272 reset( geom.type() );
273 addGeometry( geom, layer );
274}
275
277{
278 if ( geom.isNull() )
279 {
280 reset( mGeometryType );
281 return;
282 }
283
284 reset( geom.type() );
285 addGeometry( geom, crs );
286}
287
288void QgsRubberBand::addGeometry( const QgsGeometry &geometry, QgsMapLayer *layer, bool doUpdate )
289{
290 QgsGeometry geom = geometry;
291 if ( layer )
292 {
294 try
295 {
296 geom.transform( ct );
297 }
298 catch ( QgsCsException & )
299 {
300 return;
301 }
302 }
303
304 addGeometry( geom, QgsCoordinateReferenceSystem(), doUpdate );
305}
306
307void QgsRubberBand::addGeometry( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &crs, bool doUpdate )
308{
309 if ( geometry.isEmpty() )
310 {
311 return;
312 }
313
314 //maprender object of canvas
316
317 int idx = mPoints.size();
318
319 QgsGeometry geom = geometry;
320 if ( crs.isValid() )
321 {
323 try
324 {
325 geom.transform( ct );
326 }
327 catch ( QgsCsException & )
328 {
329 QgsDebugError( QStringLiteral( "Could not transform rubber band geometry to map CRS" ) );
330 return;
331 }
332 }
333
334 Qgis::WkbType geomType = geom.wkbType();
336 {
337 QgsPointXY pt = geom.asPoint();
338 addPoint( pt, false, idx );
339 }
341 {
342 const QgsMultiPointXY mpt = geom.asMultiPoint();
343 for ( const QgsPointXY &pt : mpt )
344 {
345 addPoint( pt, false, idx );
346 idx++;
347 }
348 }
349 else if ( QgsWkbTypes::geometryType( geomType ) == Qgis::GeometryType::Line && !QgsWkbTypes::isMultiType( geomType ) )
350 {
351 const QgsPolylineXY line = geom.asPolyline();
352 for ( const QgsPointXY &pt : line )
353 {
354 addPoint( pt, false, idx );
355 }
356 }
357 else if ( QgsWkbTypes::geometryType( geomType ) == Qgis::GeometryType::Line && QgsWkbTypes::isMultiType( geomType ) )
358 {
359 const QgsMultiPolylineXY mline = geom.asMultiPolyline();
360 for ( const QgsPolylineXY &line : mline )
361 {
362 if ( line.isEmpty() )
363 {
364 continue;
365 }
366 for ( const QgsPointXY &pt : line )
367 {
368 addPoint( pt, false, idx );
369 }
370 idx++;
371 }
372 }
374 {
375 const QgsPolygonXY poly = geom.asPolygon();
376 int ringIdx = 0;
377 for ( const QgsPolylineXY &ring : poly )
378 {
379 for ( const QgsPointXY &pt : ring )
380 {
381 addPoint( pt, false, idx, ringIdx );
382 }
383 ringIdx++;
384 }
385 }
387 {
388 const QgsMultiPolygonXY multipoly = geom.asMultiPolygon();
389 for ( const QgsPolygonXY &poly : multipoly )
390 {
391 if ( poly.isEmpty() )
392 continue;
393
394 int ringIdx = 0;
395 for ( const QgsPolylineXY &ring : poly )
396 {
397 for ( const QgsPointXY &pt : ring )
398 {
399 addPoint( pt, false, idx, ringIdx );
400 }
401 ringIdx++;
402 }
403 idx++;
404 }
405 }
406 else
407 {
408 return;
409 }
410
411 setVisible( true );
412 if ( doUpdate )
413 {
414 updateRect();
415 update();
416 }
417}
418
420{
421 if ( !mMapCanvas )
422 {
423 return;
424 }
425
426 const QgsMapToPixel *transform = mMapCanvas->getCoordinateTransform();
427 QgsPointXY ll = transform->toMapCoordinates( rect.left(), rect.bottom() );
428 QgsPointXY lr = transform->toMapCoordinates( rect.right(), rect.bottom() );
429 QgsPointXY ul = transform->toMapCoordinates( rect.left(), rect.top() );
430 QgsPointXY ur = transform->toMapCoordinates( rect.right(), rect.top() );
431
433 addPoint( ll, false );
434 addPoint( lr, false );
435 addPoint( ur, false );
436 addPoint( ul, true );
437}
438
440{
441 reset( other->mGeometryType );
442 mPoints = other->mPoints;
443 updateRect();
444 update();
445}
446
447void QgsRubberBand::paint( QPainter *p )
448{
449 if ( mPoints.isEmpty() )
450 return;
451
452 QVector< QVector<QPolygonF> > shapes;
453 shapes.reserve( mPoints.size() );
454 for ( const QgsPolygonXY &poly : std::as_const( mPoints ) )
455 {
456 QVector<QPolygonF> rings;
457 rings.reserve( poly.size() );
458 for ( const QgsPolylineXY &line : poly )
459 {
460 QVector<QPointF> pts;
461 pts.reserve( line.size() );
462 for ( const QgsPointXY &pt : line )
463 {
464 const QPointF cur = toCanvasCoordinates( QgsPointXY( pt.x() + mTranslationOffsetX, pt.y() + mTranslationOffsetY ) ) - pos();
465 if ( pts.isEmpty() || std::abs( pts.last().x() - cur.x() ) > 1 || std::abs( pts.last().y() - cur.y() ) > 1 )
466 pts.append( cur );
467 }
468 rings.append( pts );
469 }
470 shapes.append( rings );
471 }
472
473 if ( QgsLineSymbol *lineSymbol = dynamic_cast< QgsLineSymbol * >( mSymbol.get() ) )
474 {
477
478 lineSymbol->startRender( context );
479 for ( const QVector<QPolygonF> &shape : std::as_const( shapes ) )
480 {
481 for ( const QPolygonF &ring : shape )
482 {
483 lineSymbol->renderPolyline( ring, nullptr, context );
484 }
485 }
486 lineSymbol->stopRender( context );
487 }
488 else if ( QgsFillSymbol *fillSymbol = dynamic_cast< QgsFillSymbol * >( mSymbol.get() ) )
489 {
492
493 fillSymbol->startRender( context );
494 for ( const QVector<QPolygonF> &shape : std::as_const( shapes ) )
495 {
496 for ( const QPolygonF &ring : shape )
497 {
498 fillSymbol->renderPolygon( ring, nullptr, nullptr, context );
499 }
500 }
501 fillSymbol->stopRender( context );
502 }
503 else
504 {
505 int iterations = mSecondaryPen.color().isValid() ? 2 : 1;
506 for ( int i = 0; i < iterations; ++i )
507 {
508 if ( i == 0 && iterations > 1 )
509 {
510 // first iteration with multi-pen painting, so use secondary pen
511 mSecondaryPen.setWidth( mPen.width() + QgsGuiUtils::scaleIconSize( 2 ) );
512 p->setBrush( Qt::NoBrush );
513 p->setPen( mSecondaryPen );
514 }
515 else
516 {
517 // "top" layer, use primary pen/brush
518 p->setBrush( mBrush );
519 p->setPen( mPen );
520 }
521
522 for ( const QVector<QPolygonF> &shape : std::as_const( shapes ) )
523 {
524 drawShape( p, shape );
525 }
526 }
527 }
528}
529
530void QgsRubberBand::drawShape( QPainter *p, const QVector<QPolygonF> &rings )
531{
532 if ( rings.size() == 1 )
533 {
534 drawShape( p, rings.at( 0 ) );
535 }
536 else
537 {
538 QPainterPath path;
539 for ( const QPolygonF &poly : rings )
540 {
541 path.addPolygon( poly );
542 }
543 p->drawPath( path );
544 }
545}
546
547void QgsRubberBand::drawShape( QPainter *p, const QVector<QPointF> &pts )
548{
549 switch ( mGeometryType )
550 {
552 {
553 p->drawPolygon( pts );
554 }
555 break;
556
558 {
559 const auto constPts = pts;
560 for ( QPointF pt : constPts )
561 {
562 double x = pt.x();
563 double y = pt.y();
564
565 qreal s = ( mIconSize - 1 ) / 2.0;
566
567 switch ( mIconType )
568 {
569 case ICON_NONE:
570 break;
571
572 case ICON_CROSS:
573 p->drawLine( QLineF( x - s, y, x + s, y ) );
574 p->drawLine( QLineF( x, y - s, x, y + s ) );
575 break;
576
577 case ICON_X:
578 p->drawLine( QLineF( x - s, y - s, x + s, y + s ) );
579 p->drawLine( QLineF( x - s, y + s, x + s, y - s ) );
580 break;
581
582 case ICON_BOX:
583 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 break;
588
589 case ICON_FULL_BOX:
590 p->drawRect( static_cast< int>( x - s ), static_cast< int >( y - s ), mIconSize, mIconSize );
591 break;
592
593 case ICON_CIRCLE:
594 p->drawEllipse( static_cast< int >( x - s ), static_cast< int >( y - s ), mIconSize, mIconSize );
595 break;
596
597 case ICON_DIAMOND:
599 {
600 QPointF pts[] =
601 {
602 QPointF( x, y - s ),
603 QPointF( x + s, y ),
604 QPointF( x, y + s ),
605 QPointF( x - s, y )
606 };
607 if ( mIconType == ICON_FULL_DIAMOND )
608 p->drawPolygon( pts, 4 );
609 else
610 p->drawPolyline( pts, 4 );
611 break;
612 }
613
614 case ICON_SVG:
615 {
616 QRectF viewBox = mSvgRenderer->viewBoxF();
617 QRectF r( mSvgOffset.x(), mSvgOffset.y(), viewBox.width(), viewBox.height() );
618 QgsScopedQPainterState painterState( p );
619 p->translate( pt );
620 mSvgRenderer->render( p, r );
621 break;
622 }
623 }
624 }
625 }
626 break;
627
629 default:
630 {
631 p->drawPolyline( pts );
632 }
633 break;
634 }
635}
636
638{
639 if ( mPoints.isEmpty() )
640 {
642 setVisible( false );
643 return;
644 }
645
647
648#if 0 // unused?
649 double iconSize = ( mIconSize + 1 ) / 2.;
650 if ( mSvgRenderer )
651 {
652 QRectF viewBox = mSvgRenderer->viewBoxF();
653 iconSize = std::max( std::fabs( mSvgOffset.x() ) + .5 * viewBox.width(), std::fabs( mSvgOffset.y() ) + .5 * viewBox.height() );
654 }
655#endif
656
657 qreal w = ( ( mIconSize - 1 ) / 2 + mPen.width() ); // in canvas units
658
659 QgsRectangle r; // in canvas units
660 for ( const QgsPolygonXY &poly : std::as_const( mPoints ) )
661 {
662 for ( const QgsPointXY &point : poly.at( 0 ) )
663 {
664 QgsPointXY p( point.x() + mTranslationOffsetX, point.y() + mTranslationOffsetY );
665 p = m2p.transform( p );
666 // no need to normalize the rectangle -- we know it is already normal
667 QgsRectangle rect( p.x() - w, p.y() - w, p.x() + w, p.y() + w, false );
669 }
670 }
671
672 // This is an hack to pass QgsMapCanvasItem::setRect what it
673 // expects (encoding of position and size of the item)
674 qreal res = m2p.mapUnitsPerPixel();
675 QgsPointXY topLeft = m2p.toMapCoordinates( r.xMinimum(), r.yMinimum() );
676 QgsRectangle rect( topLeft.x(), topLeft.y(), topLeft.x() + r.width()*res, topLeft.y() - r.height()*res );
677
678 setRect( rect );
679}
680
682{
683 return mSymbol.get();
684}
685
687{
688 mSymbol.reset( symbol );
689}
690
692{
693 // re-compute rectangle
694 // See https://github.com/qgis/QGIS/issues/20566
695 // NOTE: could be optimized by saving map-extent
696 // of rubberband and simply re-projecting
697 // that to device-rectangle on "updatePosition"
698 updateRect();
699}
700
701void QgsRubberBand::setTranslationOffset( double dx, double dy )
702{
703 mTranslationOffsetX = dx;
704 mTranslationOffsetY = dy;
705 updateRect();
706}
707
709{
710 return mPoints.size();
711}
712
713int QgsRubberBand::partSize( int geometryIndex ) const
714{
715 if ( geometryIndex < 0 ||
716 geometryIndex >= mPoints.size() ||
717 mPoints.at( geometryIndex ).isEmpty() )
718 return 0;
719 return mPoints.at( geometryIndex ).at( 0 ).size();
720}
721
723{
724 int count = 0;
725 for ( const QgsPolygonXY &poly : std::as_const( mPoints ) )
726 {
727 for ( const QgsPolylineXY &ring : poly )
728 {
729 count += ring.size();
730 }
731 }
732 return count;
733}
734
735const QgsPointXY *QgsRubberBand::getPoint( int i, int j, int ringIndex ) const
736{
737 if ( i < 0 || ringIndex < 0 || j < 0 ||
738 mPoints.size() <= i ||
739 mPoints.at( i ).size() <= ringIndex ||
740 mPoints.at( i ).at( ringIndex ).size() <= j )
741 return nullptr;
742 else
743 return &mPoints[i][ringIndex][j];
744}
745
747{
748 QgsGeometry geom;
749
750 switch ( mGeometryType )
751 {
753 {
754 geom = QgsGeometry::fromMultiPolygonXY( mPoints );
755 break;
756 }
757
759 {
760 QgsMultiPointXY multiPoint;
761
762 for ( const QgsPolygonXY &poly : std::as_const( mPoints ) )
763 {
764 if ( poly.isEmpty() )
765 continue;
766 multiPoint.append( poly.at( 0 ) );
767 }
768 geom = QgsGeometry::fromMultiPointXY( multiPoint );
769 break;
770 }
771
773 default:
774 {
775 if ( !mPoints.isEmpty() )
776 {
777 if ( mPoints.size() > 1 )
778 {
779 QgsMultiPolylineXY multiPolyline;
780 for ( const QgsPolygonXY &poly : std::as_const( mPoints ) )
781 {
782 if ( poly.isEmpty() )
783 continue;
784 multiPolyline.append( poly.at( 0 ) );
785 }
786 geom = QgsGeometry::fromMultiPolylineXY( multiPolyline );
787 }
788 else
789 {
790 if ( !mPoints.at( 0 ).isEmpty() )
791 geom = QgsGeometry::fromPolylineXY( mPoints.at( 0 ).at( 0 ) );
792 else
794 }
795 }
796 break;
797 }
798 }
799 return geom;
800}
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
Definition qgis.h:274
@ Polygon
Polygons.
@ Antialiasing
Use antialiasing while drawing.
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:201
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.
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.
Qgis::GeometryType type
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.
Definition qgsmaplayer.h:75
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.
Definition qgspointxy.h:60
double y
Definition qgspointxy.h:64
double x
Definition qgspointxy.h:63
static QgsProject * instance()
Returns the QgsProject singleton instance.
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double width() const
Returns the width of the rectangle.
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
double height() const
Returns the height of the 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 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 setWidth(int width)
Sets the width of the line.
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 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 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 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.
Definition qgssymbol.h:94
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.
Definition qgsgeometry.h:74
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
Definition qgsgeometry.h:84
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
Definition qgsgeometry.h:80
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Definition qgsgeometry.h:62
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
Definition qgsgeometry.h:91
#define QgsDebugError(str)
Definition qgslogger.h:38
const QgsCoordinateReferenceSystem & crs