1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qpolygon.h"
5#include "qrect.h"
6#include "qdatastream.h"
7#include "qdebug.h"
8#include "qpainterpath.h"
9#include "qtransform.h"
10#include "qvariant.h"
11#include "qpainterpath_p.h"
12#include "qbezier_p.h"
13
14#include <stdarg.h>
15
16QT_BEGIN_NAMESPACE
17
18//same as qt_painterpath_isect_line in qpainterpath.cpp
19static void qt_polygon_isect_line(const QPointF &p1, const QPointF &p2, const QPointF &pos,
20 int *winding)
21{
22 qreal x1 = p1.x();
23 qreal y1 = p1.y();
24 qreal x2 = p2.x();
25 qreal y2 = p2.y();
26 qreal y = pos.y();
27
28 int dir = 1;
29
30 if (qFuzzyCompare(p1: y1, p2: y2)) {
31 // ignore horizontal lines according to scan conversion rule
32 return;
33 } else if (y2 < y1) {
34 qreal x_tmp = x2; x2 = x1; x1 = x_tmp;
35 qreal y_tmp = y2; y2 = y1; y1 = y_tmp;
36 dir = -1;
37 }
38
39 if (y >= y1 && y < y2) {
40 qreal x = x1 + ((x2 - x1) / (y2 - y1)) * (y - y1);
41
42 // count up the winding number if we're
43 if (x<=pos.x()) {
44 (*winding) += dir;
45 }
46 }
47}
48
49/*!
50 \class QPolygon
51 \brief The QPolygon class provides a list of points using
52 integer precision.
53 \inmodule QtGui
54
55 \reentrant
56
57 \ingroup painting
58 \ingroup shared
59
60 A QPolygon object is a QList<QPoint>. The easiest way to add
61 points to a QPolygon is to use QList's streaming operator, as
62 illustrated below:
63
64 \snippet polygon/polygon.cpp 0
65
66 In addition to the functions provided by QList, QPolygon
67 provides some point-specific functions.
68
69 Each point in a polygon can be retrieved by passing its index to
70 the point() function. To populate the polygon, QPolygon provides
71 the setPoint() function to set the point at a given index, the
72 setPoints() function to set all the points in the polygon
73 (resizing it to the given number of points), and the putPoints()
74 function which copies a number of given points into the polygon
75 from a specified index (resizing the polygon if necessary).
76
77 QPolygon provides the boundingRect() and translate() functions for
78 geometry functions. Use the QTransform::map() function for more
79 general transformations of QPolygons.
80
81 The QPolygon class is \l {Implicit Data Sharing}{implicitly
82 shared}.
83
84 \sa QList, QPolygonF, QLine
85*/
86
87
88/*****************************************************************************
89 QPolygon member functions
90 *****************************************************************************/
91
92/*!
93 \fn QPolygon::QPolygon()
94
95 Constructs a polygon with no points.
96
97 \sa QList::isEmpty()
98*/
99
100/*!
101 \fn QPolygon::QPolygon(const QList<QPoint> &points)
102
103 Constructs a polygon containing the specified \a points.
104
105 \sa setPoints()
106*/
107
108/*!
109 \fn QPolygon::QPolygon(const QRect &rectangle, bool closed)
110
111 Constructs a polygon from the given \a rectangle. If \a closed is
112 false, the polygon just contains the four points of the rectangle
113 ordered clockwise, otherwise the polygon's fifth point is set to
114 \a {rectangle}.topLeft().
115
116 Note that the bottom-right corner of the rectangle is located at
117 (rectangle.x() + rectangle.width(), rectangle.y() +
118 rectangle.height()).
119
120 \sa setPoints()
121*/
122
123QPolygon::QPolygon(const QRect &r, bool closed)
124{
125 reserve(asize: closed ? 5 : 4);
126 *this << QPoint(r.x(), r.y())
127 << QPoint(r.x() + r.width(), r.y())
128 << QPoint(r.x() + r.width(), r.y() + r.height())
129 << QPoint(r.x(), r.y() + r.height());
130 if (closed)
131 *this << QPoint(r.left(), r.top());
132}
133
134/*!
135 \internal
136 Constructs a point array with \a nPoints points, taken from the
137 \a points array.
138
139 Equivalent to setPoints(nPoints, points).
140*/
141
142QPolygon::QPolygon(int nPoints, const int *points)
143{
144 setPoints(nPoints, points);
145}
146
147/*!
148 Translates all points in the polygon by (\a{dx}, \a{dy}).
149
150 \sa translated()
151*/
152
153void QPolygon::translate(int dx, int dy)
154{
155 if (dx == 0 && dy == 0)
156 return;
157
158 QPoint *p = data();
159 int i = size();
160 QPoint pt(dx, dy);
161 while (i--) {
162 *p += pt;
163 ++p;
164 }
165}
166
167/*!
168 \fn void QPolygon::translate(const QPoint &offset)
169 \overload
170
171 Translates all points in the polygon by the given \a offset.
172
173 \sa translated()
174*/
175
176/*!
177 Returns a copy of the polygon that is translated by (\a{dx}, \a{dy}).
178
179 \since 4.6
180 \sa translate()
181*/
182QPolygon QPolygon::translated(int dx, int dy) const
183{
184 QPolygon copy(*this);
185 copy.translate(dx, dy);
186 return copy;
187}
188
189/*!
190 \fn void QPolygon::translated(const QPoint &offset) const
191 \overload
192 \since 4.6
193
194 Returns a copy of the polygon that is translated by the given \a offset.
195
196 \sa translate()
197*/
198
199/*!
200 Extracts the coordinates of the point at the given \a index to
201 *\a{x} and *\a{y} (if they are valid pointers).
202
203 \sa setPoint()
204*/
205
206void QPolygon::point(int index, int *x, int *y) const
207{
208 QPoint p = at(i: index);
209 if (x)
210 *x = (int)p.x();
211 if (y)
212 *y = (int)p.y();
213}
214
215/*!
216 \fn QPoint QPolygon::point(int index) const
217 \overload
218
219 Returns the point at the given \a index.
220*/
221
222/*!
223 \fn void QPolygon::setPoint(int index, const QPoint &point)
224 \overload
225
226 Sets the point at the given \a index to the given \a point.
227*/
228
229/*!
230 Sets the point at the given \a index to the point specified by
231 (\a{x}, \a{y}).
232
233 \sa point(), putPoints(), setPoints(),
234*/
235void QPolygon::setPoint(int index, int x, int y)
236{
237 (*this)[index] = QPoint(x, y);
238}
239
240
241/*!
242 Resizes the polygon to \a nPoints and populates it with the given
243 \a points.
244
245 The example code creates a polygon with two points (10, 20) and
246 (30, 40):
247
248 \snippet polygon/polygon.cpp 2
249
250 \sa setPoint(), putPoints()
251*/
252
253void QPolygon::setPoints(int nPoints, const int *points)
254{
255 resize(size: nPoints);
256 int i = 0;
257 while (nPoints--) {
258 setPoint(index: i++, x: *points, y: *(points+1));
259 points += 2;
260 }
261}
262
263/*!
264 \overload
265
266 Resizes the polygon to \a nPoints and populates it with the points
267 specified by the variable argument list. The points are given as a
268 sequence of integers, starting with \a firstx then \a firsty, and
269 so on.
270
271 The example code creates a polygon with two points (10, 20) and
272 (30, 40):
273
274 \snippet polygon/polygon.cpp 3
275*/
276
277void QPolygon::setPoints(int nPoints, int firstx, int firsty, ...)
278{
279 va_list ap;
280 resize(size: nPoints);
281 setPoint(index: 0, x: firstx, y: firsty);
282 int i = 0, x, y;
283 va_start(ap, firsty);
284 while (--nPoints) {
285 x = va_arg(ap, int);
286 y = va_arg(ap, int);
287 setPoint(index: ++i, x, y);
288 }
289 va_end(ap);
290}
291
292/*!
293 \overload
294 \internal
295
296 Copies \a nPoints points from the \a points coord array into this
297 point array, and resizes the point array if \c{index+nPoints}
298 exceeds the size of the array.
299
300 \sa setPoint()
301*/
302
303void QPolygon::putPoints(int index, int nPoints, const int *points)
304{
305 if (index + nPoints > size())
306 resize(size: index + nPoints);
307 int i = index;
308 while (nPoints--) {
309 setPoint(index: i++, x: *points, y: *(points+1));
310 points += 2;
311 }
312}
313
314/*!
315 Copies \a nPoints points from the variable argument list into this
316 polygon from the given \a index.
317
318 The points are given as a sequence of integers, starting with \a
319 firstx then \a firsty, and so on. The polygon is resized if
320 \c{index+nPoints} exceeds its current size.
321
322 The example code creates a polygon with three points (4,5), (6,7)
323 and (8,9), by expanding the polygon from 1 to 3 points:
324
325 \snippet polygon/polygon.cpp 4
326
327 The following code has the same result, but here the putPoints()
328 function overwrites rather than extends:
329
330 \snippet polygon/polygon.cpp 5
331
332 \sa setPoints()
333*/
334
335void QPolygon::putPoints(int index, int nPoints, int firstx, int firsty, ...)
336{
337 va_list ap;
338 if (index + nPoints > size())
339 resize(size: index + nPoints);
340 if (nPoints <= 0)
341 return;
342 setPoint(index, x: firstx, y: firsty);
343 int i = index, x, y;
344 va_start(ap, firsty);
345 while (--nPoints) {
346 x = va_arg(ap, int);
347 y = va_arg(ap, int);
348 setPoint(index: ++i, x, y);
349 }
350 va_end(ap);
351}
352
353
354/*!
355 \fn void QPolygon::putPoints(int index, int nPoints, const QPolygon &fromPolygon, int fromIndex)
356 \overload
357
358 Copies \a nPoints points from the given \a fromIndex ( 0 by
359 default) in \a fromPolygon into this polygon, starting at the
360 specified \a index. For example:
361
362 \snippet polygon/polygon.cpp 6
363*/
364
365void QPolygon::putPoints(int index, int nPoints, const QPolygon & from, int fromIndex)
366{
367 if (index + nPoints > size())
368 resize(size: index + nPoints);
369 if (nPoints <= 0)
370 return;
371 int n = 0;
372 while(n < nPoints) {
373 setPoint(index: index + n, pt: from[fromIndex+n]);
374 ++n;
375 }
376}
377
378
379/*!
380 Returns the bounding rectangle of the polygon, or QRect(0, 0, 0,
381 0) if the polygon is empty.
382
383 \sa QList::isEmpty()
384*/
385
386QRect QPolygon::boundingRect() const
387{
388 const QPoint *pd = constData();
389 const QPoint *pe = pd + size();
390 if (pd == pe)
391 return QRect(0, 0, 0, 0);
392 int minx, maxx, miny, maxy;
393 minx = maxx = pd->x();
394 miny = maxy = pd->y();
395 ++pd;
396 for (; pd != pe; ++pd) {
397 if (pd->x() < minx)
398 minx = pd->x();
399 else if (pd->x() > maxx)
400 maxx = pd->x();
401 if (pd->y() < miny)
402 miny = pd->y();
403 else if (pd->y() > maxy)
404 maxy = pd->y();
405 }
406 return QRect(QPoint(minx,miny), QPoint(maxx,maxy));
407}
408
409/*!
410 \fn QPolygon::toPolygonF() const
411 \since 6.4
412
413 Returns this polygon as a polygon with floating point accuracy.
414
415 \sa QPolygonF::toPolygon()
416*/
417
418
419#ifndef QT_NO_DEBUG_STREAM
420QDebug operator<<(QDebug dbg, const QPolygon &a)
421{
422 return QtPrivate::printSequentialContainer(debug: dbg, which: "QPolygon", c: a);
423}
424#endif
425
426
427/*!
428 \class QPolygonF
429 \brief The QPolygonF class provides a list of points using
430 floating point precision.
431 \inmodule QtGui
432
433 \reentrant
434 \ingroup painting
435 \ingroup shared
436
437 A QPolygonF is a QList<QPointF>. The easiest way to add points
438 to a QPolygonF is to use its streaming operator, as illustrated
439 below:
440
441 \snippet polygon/polygon.cpp 1
442
443 In addition to the functions provided by QList, QPolygonF
444 provides the boundingRect() and translate() functions for geometry
445 operations. Use the QTransform::map() function for more general
446 transformations of QPolygonFs.
447
448 QPolygonF also provides the isClosed() function to determine
449 whether a polygon's start and end points are the same, and the
450 toPolygon() function returning an integer precision copy of this
451 polygon.
452
453 The QPolygonF class is \l {Implicit Data Sharing}{implicitly
454 shared}.
455
456 \sa QList, QPolygon, QLineF
457*/
458
459
460/*****************************************************************************
461 QPolygonF member functions
462 *****************************************************************************/
463
464/*!
465 \fn QPolygonF::QPolygonF()
466
467 Constructs a polygon with no points.
468
469 \sa QList::isEmpty()
470*/
471
472/*!
473 \fn QPolygonF::QPolygonF(const QList<QPointF> &points)
474
475 Constructs a polygon containing the specified \a points.
476*/
477
478/*!
479 \fn QPolygonF::QPolygonF(const QRectF &rectangle)
480
481 Constructs a closed polygon from the specified \a rectangle.
482
483 The polygon contains the four vertices of the rectangle in
484 clockwise order starting and ending with the top-left vertex.
485
486 \sa isClosed()
487*/
488
489QPolygonF::QPolygonF(const QRectF &r)
490{
491 reserve(asize: 5);
492 append(t: QPointF(r.x(), r.y()));
493 append(t: QPointF(r.x() + r.width(), r.y()));
494 append(t: QPointF(r.x() + r.width(), r.y() + r.height()));
495 append(t: QPointF(r.x(), r.y() + r.height()));
496 append(t: QPointF(r.x(), r.y()));
497}
498
499/*!
500 \fn QPolygonF::QPolygonF(const QPolygon &polygon)
501
502 Constructs a float based polygon from the specified integer based
503 \a polygon.
504
505 \sa toPolygon()
506*/
507
508QPolygonF::QPolygonF(const QPolygon &a)
509{
510 reserve(asize: a.size());
511 for (int i=0; i<a.size(); ++i)
512 append(t: a.at(i));
513}
514
515/*!
516 Translate all points in the polygon by the given \a offset.
517
518 \sa translated()
519*/
520
521void QPolygonF::translate(const QPointF &offset)
522{
523 if (offset.isNull())
524 return;
525
526 QPointF *p = data();
527 int i = size();
528 while (i--) {
529 *p += offset;
530 ++p;
531 }
532}
533
534/*!
535 \fn void QPolygonF::translate(qreal dx, qreal dy)
536 \overload
537
538 Translates all points in the polygon by (\a{dx}, \a{dy}).
539
540 \sa translated()
541*/
542
543/*!
544 Returns a copy of the polygon that is translated by the given \a offset.
545
546 \since 4.6
547 \sa translate()
548*/
549QPolygonF QPolygonF::translated(const QPointF &offset) const
550{
551 QPolygonF copy(*this);
552 copy.translate(offset);
553 return copy;
554}
555
556/*!
557 \fn void QPolygonF::translated(qreal dx, qreal dy) const
558 \overload
559 \since 4.6
560
561 Returns a copy of the polygon that is translated by (\a{dx}, \a{dy}).
562
563 \sa translate()
564*/
565
566/*!
567 \fn bool QPolygonF::isClosed() const
568
569 Returns \c true if the polygon is closed; otherwise returns \c false.
570
571 A polygon is said to be closed if its start point and end point are equal.
572
573 \sa QList::first(), QList::last()
574*/
575
576/*!
577 Returns the bounding rectangle of the polygon, or QRectF(0,0,0,0)
578 if the polygon is empty.
579
580 \sa QList::isEmpty()
581*/
582
583QRectF QPolygonF::boundingRect() const
584{
585 const QPointF *pd = constData();
586 const QPointF *pe = pd + size();
587 if (pd == pe)
588 return QRectF(0, 0, 0, 0);
589 qreal minx, maxx, miny, maxy;
590 minx = maxx = pd->x();
591 miny = maxy = pd->y();
592 ++pd;
593 while (pd != pe) {
594 if (pd->x() < minx)
595 minx = pd->x();
596 else if (pd->x() > maxx)
597 maxx = pd->x();
598 if (pd->y() < miny)
599 miny = pd->y();
600 else if (pd->y() > maxy)
601 maxy = pd->y();
602 ++pd;
603 }
604 return QRectF(minx,miny, maxx - minx, maxy - miny);
605}
606
607/*!
608 Creates and returns a QPolygon by converting each QPointF to a
609 QPoint.
610
611 \sa QPointF::toPoint()
612*/
613
614QPolygon QPolygonF::toPolygon() const
615{
616 QPolygon a;
617 a.reserve(asize: size());
618 for (int i=0; i<size(); ++i)
619 a.append(t: at(i).toPoint());
620 return a;
621}
622
623/*!
624 \fn void QPolygon::swap(QPolygon &other)
625 \since 4.8
626
627 Swaps polygon \a other with this polygon. This operation is very
628 fast and never fails.
629*/
630
631/*!
632 \fn void QPolygonF::swap(QPolygonF &other)
633 \since 4.8
634
635 Swaps polygon \a other with this polygon. This operation is very
636 fast and never fails.
637*/
638
639/*!
640 Returns the polygon as a QVariant
641*/
642QPolygon::operator QVariant() const
643{
644 return QVariant::fromValue(value: *this);
645}
646
647/*****************************************************************************
648 QPolygon stream functions
649 *****************************************************************************/
650#ifndef QT_NO_DATASTREAM
651/*!
652 \fn QDataStream &operator<<(QDataStream &stream, const QPolygon &polygon)
653 \since 4.4
654 \relates QPolygon
655
656 Writes the given \a polygon to the given \a stream, and returns a
657 reference to the stream.
658
659 \sa {Serializing Qt Data Types}
660*/
661QDataStream &operator<<(QDataStream &s, const QPolygon &a)
662{
663 const QList<QPoint> &v = a;
664 return s << v;
665}
666
667/*!
668 \fn QDataStream &operator>>(QDataStream &stream, QPolygon &polygon)
669 \since 4.4
670 \relates QPolygon
671
672 Reads a polygon from the given \a stream into the given \a
673 polygon, and returns a reference to the stream.
674
675 \sa {Serializing Qt Data Types}
676*/
677QDataStream &operator>>(QDataStream &s, QPolygon &a)
678{
679 QList<QPoint> &v = a;
680 return s >> v;
681}
682#endif // QT_NO_DATASTREAM
683
684/*****************************************************************************
685 QPolygonF stream functions
686 *****************************************************************************/
687#ifndef QT_NO_DATASTREAM
688/*!
689 \fn QDataStream &operator<<(QDataStream &stream, const QPolygonF &polygon)
690 \relates QPolygonF
691
692 Writes the given \a polygon to the given \a stream, and returns a
693 reference to the stream.
694
695 \sa {Serializing Qt Data Types}
696*/
697
698QDataStream &operator<<(QDataStream &s, const QPolygonF &a)
699{
700 quint32 len = a.size();
701 uint i;
702
703 s << len;
704 for (i = 0; i < len; ++i)
705 s << a.at(i);
706 return s;
707}
708
709/*!
710 \fn QDataStream &operator>>(QDataStream &stream, QPolygonF &polygon)
711 \relates QPolygonF
712
713 Reads a polygon from the given \a stream into the given \a
714 polygon, and returns a reference to the stream.
715
716 \sa {Serializing Qt Data Types}
717*/
718
719QDataStream &operator>>(QDataStream &s, QPolygonF &a)
720{
721 quint32 len;
722 uint i;
723
724 s >> len;
725 a.reserve(asize: a.size() + (int)len);
726 QPointF p;
727 for (i = 0; i < len; ++i) {
728 s >> p;
729 a.insert(i, t: p);
730 }
731 return s;
732}
733#endif //QT_NO_DATASTREAM
734
735#ifndef QT_NO_DEBUG_STREAM
736QDebug operator<<(QDebug dbg, const QPolygonF &a)
737{
738 return QtPrivate::printSequentialContainer(debug: dbg, which: "QPolygonF", c: a);
739}
740#endif
741
742
743/*!
744 \since 4.3
745
746 \fn bool QPolygonF::containsPoint(const QPointF &point, Qt::FillRule fillRule) const
747
748 Returns \c true if the given \a point is inside the polygon according to
749 the specified \a fillRule; otherwise returns \c false.
750*/
751bool QPolygonF::containsPoint(const QPointF &pt, Qt::FillRule fillRule) const
752{
753 if (isEmpty())
754 return false;
755
756 int winding_number = 0;
757
758 QPointF last_pt = at(i: 0);
759 QPointF last_start = at(i: 0);
760 for (int i = 1; i < size(); ++i) {
761 const QPointF &e = at(i);
762 qt_polygon_isect_line(p1: last_pt, p2: e, pos: pt, winding: &winding_number);
763 last_pt = e;
764 }
765
766 // implicitly close last subpath
767 if (last_pt != last_start)
768 qt_polygon_isect_line(p1: last_pt, p2: last_start, pos: pt, winding: &winding_number);
769
770 return (fillRule == Qt::WindingFill
771 ? (winding_number != 0)
772 : ((winding_number % 2) != 0));
773}
774
775/*!
776 \since 4.3
777
778 \fn bool QPolygon::containsPoint(const QPoint &point, Qt::FillRule fillRule) const
779 Returns \c true if the given \a point is inside the polygon according to
780 the specified \a fillRule; otherwise returns \c false.
781*/
782bool QPolygon::containsPoint(const QPoint &pt, Qt::FillRule fillRule) const
783{
784 if (isEmpty())
785 return false;
786
787 int winding_number = 0;
788
789 QPoint last_pt = at(i: 0);
790 QPoint last_start = at(i: 0);
791 for (int i = 1; i < size(); ++i) {
792 const QPoint &e = at(i);
793 qt_polygon_isect_line(p1: last_pt, p2: e, pos: pt, winding: &winding_number);
794 last_pt = e;
795 }
796
797 // implicitly close last subpath
798 if (last_pt != last_start)
799 qt_polygon_isect_line(p1: last_pt, p2: last_start, pos: pt, winding: &winding_number);
800
801 return (fillRule == Qt::WindingFill
802 ? (winding_number != 0)
803 : ((winding_number % 2) != 0));
804}
805
806/*!
807 \since 4.3
808
809 Returns a polygon which is the union of this polygon and \a r.
810
811 Set operations on polygons, will treat the polygons as areas, and
812 implicitly close the polygon.
813
814 \sa intersected(), subtracted()
815*/
816
817QPolygon QPolygon::united(const QPolygon &r) const
818{
819 QPainterPath subject; subject.addPolygon(polygon: *this);
820 QPainterPath clip; clip.addPolygon(polygon: r);
821
822 return subject.united(r: clip).toFillPolygon().toPolygon();
823}
824
825/*!
826 \since 4.3
827
828 Returns a polygon which is the intersection of this polygon and \a r.
829
830 Set operations on polygons will treat the polygons as
831 areas. Non-closed polygons will be treated as implicitly closed.
832
833 \sa intersects()
834*/
835
836QPolygon QPolygon::intersected(const QPolygon &r) const
837{
838 QPainterPath subject; subject.addPolygon(polygon: *this);
839 QPainterPath clip; clip.addPolygon(polygon: r);
840
841 return subject.intersected(r: clip).toFillPolygon().toPolygon();
842}
843
844/*!
845 \since 4.3
846
847 Returns a polygon which is \a r subtracted from this polygon.
848
849 Set operations on polygons will treat the polygons as
850 areas. Non-closed polygons will be treated as implicitly closed.
851
852*/
853
854QPolygon QPolygon::subtracted(const QPolygon &r) const
855{
856 QPainterPath subject; subject.addPolygon(polygon: *this);
857 QPainterPath clip; clip.addPolygon(polygon: r);
858
859 return subject.subtracted(r: clip).toFillPolygon().toPolygon();
860}
861
862/*!
863 \since 5.10
864
865 Returns \c true if the current polygon intersects at any point the given polygon \a p.
866 Also returns \c true if the current polygon contains or is contained by any part of \a p.
867
868 Set operations on polygons will treat the polygons as
869 areas. Non-closed polygons will be treated as implicitly closed.
870
871 \sa intersected()
872*/
873
874bool QPolygon::intersects(const QPolygon &p) const
875{
876 QPainterPath subject; subject.addPolygon(polygon: *this);
877 QPainterPath clip; clip.addPolygon(polygon: p);
878
879 return subject.intersects(p: clip);
880}
881
882/*!
883 \since 4.3
884
885 Returns a polygon which is the union of this polygon and \a r.
886
887 Set operations on polygons will treat the polygons as
888 areas. Non-closed polygons will be treated as implicitly closed.
889
890 \sa intersected(), subtracted()
891*/
892
893QPolygonF QPolygonF::united(const QPolygonF &r) const
894{
895 QPainterPath subject; subject.addPolygon(polygon: *this);
896 QPainterPath clip; clip.addPolygon(polygon: r);
897
898 return subject.united(r: clip).toFillPolygon();
899}
900
901/*!
902 \since 4.3
903
904 Returns a polygon which is the intersection of this polygon and \a r.
905
906 Set operations on polygons will treat the polygons as
907 areas. Non-closed polygons will be treated as implicitly closed.
908
909 \sa intersects()
910*/
911
912QPolygonF QPolygonF::intersected(const QPolygonF &r) const
913{
914 QPainterPath subject; subject.addPolygon(polygon: *this);
915 QPainterPath clip; clip.addPolygon(polygon: r);
916
917 return subject.intersected(r: clip).toFillPolygon();
918}
919
920/*!
921 \since 4.3
922
923 Returns a polygon which is \a r subtracted from this polygon.
924
925 Set operations on polygons will treat the polygons as
926 areas. Non-closed polygons will be treated as implicitly closed.
927
928*/
929
930QPolygonF QPolygonF::subtracted(const QPolygonF &r) const
931{
932 QPainterPath subject; subject.addPolygon(polygon: *this);
933 QPainterPath clip; clip.addPolygon(polygon: r);
934 return subject.subtracted(r: clip).toFillPolygon();
935}
936
937/*!
938 \since 5.10
939
940 Returns \c true if the current polygon intersects at any point the given polygon \a p.
941 Also returns \c true if the current polygon contains or is contained by any part of \a p.
942
943 Set operations on polygons will treat the polygons as
944 areas. Non-closed polygons will be treated as implicitly closed.
945
946 \sa intersected()
947*/
948
949bool QPolygonF::intersects(const QPolygonF &p) const
950{
951 QPainterPath subject; subject.addPolygon(polygon: *this);
952 QPainterPath clip; clip.addPolygon(polygon: p);
953
954 return subject.intersects(p: clip);
955}
956
957/*!
958 Returns the polygon as a QVariant.
959*/
960
961QPolygonF::operator QVariant() const
962{
963 return QVariant::fromValue(value: *this);
964}
965
966QT_END_NAMESPACE
967

source code of qtbase/src/gui/painting/qpolygon.cpp