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