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 return s << static_cast<const QList<QPointF> &>(a);
701}
702
703/*!
704 \fn QDataStream &operator>>(QDataStream &stream, QPolygonF &polygon)
705 \relates QPolygonF
706
707 Reads a polygon from the given \a stream into the given \a
708 polygon, and returns a reference to the stream.
709
710 \sa {Serializing Qt Data Types}
711*/
712
713QDataStream &operator>>(QDataStream &s, QPolygonF &a)
714{
715 return s >> static_cast<QList<QPointF> &>(a);
716}
717#endif //QT_NO_DATASTREAM
718
719#ifndef QT_NO_DEBUG_STREAM
720QDebug operator<<(QDebug dbg, const QPolygonF &a)
721{
722 return QtPrivate::printSequentialContainer(debug: dbg, which: "QPolygonF", c: a);
723}
724#endif
725
726
727/*!
728 \since 4.3
729
730 \fn bool QPolygonF::containsPoint(const QPointF &point, Qt::FillRule fillRule) const
731
732 Returns \c true if the given \a point is inside the polygon according to
733 the specified \a fillRule; otherwise returns \c false.
734*/
735bool QPolygonF::containsPoint(const QPointF &pt, Qt::FillRule fillRule) const
736{
737 if (isEmpty())
738 return false;
739
740 int winding_number = 0;
741
742 QPointF last_pt = at(i: 0);
743 QPointF last_start = at(i: 0);
744 for (int i = 1; i < size(); ++i) {
745 const QPointF &e = at(i);
746 qt_polygon_isect_line(p1: last_pt, p2: e, pos: pt, winding: &winding_number);
747 last_pt = e;
748 }
749
750 // implicitly close last subpath
751 if (last_pt != last_start)
752 qt_polygon_isect_line(p1: last_pt, p2: last_start, pos: pt, winding: &winding_number);
753
754 return (fillRule == Qt::WindingFill
755 ? (winding_number != 0)
756 : ((winding_number % 2) != 0));
757}
758
759/*!
760 \since 4.3
761
762 \fn bool QPolygon::containsPoint(const QPoint &point, Qt::FillRule fillRule) const
763 Returns \c true if the given \a point is inside the polygon according to
764 the specified \a fillRule; otherwise returns \c false.
765*/
766bool QPolygon::containsPoint(const QPoint &pt, Qt::FillRule fillRule) const
767{
768 if (isEmpty())
769 return false;
770
771 int winding_number = 0;
772
773 QPoint last_pt = at(i: 0);
774 QPoint last_start = at(i: 0);
775 for (int i = 1; i < size(); ++i) {
776 const QPoint &e = at(i);
777 qt_polygon_isect_line(p1: last_pt, p2: e, pos: pt, winding: &winding_number);
778 last_pt = e;
779 }
780
781 // implicitly close last subpath
782 if (last_pt != last_start)
783 qt_polygon_isect_line(p1: last_pt, p2: last_start, pos: pt, winding: &winding_number);
784
785 return (fillRule == Qt::WindingFill
786 ? (winding_number != 0)
787 : ((winding_number % 2) != 0));
788}
789
790/*!
791 \since 4.3
792
793 Returns a polygon which is the union of this polygon and \a r.
794
795 Set operations on polygons, will treat the polygons as areas, and
796 implicitly close the polygon.
797
798 \sa intersected(), subtracted()
799*/
800
801QPolygon QPolygon::united(const QPolygon &r) const
802{
803 QPainterPath subject; subject.addPolygon(polygon: *this);
804 QPainterPath clip; clip.addPolygon(polygon: r);
805
806 return subject.united(r: clip).toFillPolygon().toPolygon();
807}
808
809/*!
810 \since 4.3
811
812 Returns a polygon which is the intersection of this polygon and \a r.
813
814 Set operations on polygons will treat the polygons as
815 areas. Non-closed polygons will be treated as implicitly closed.
816
817 \sa intersects()
818*/
819
820QPolygon QPolygon::intersected(const QPolygon &r) const
821{
822 QPainterPath subject; subject.addPolygon(polygon: *this);
823 QPainterPath clip; clip.addPolygon(polygon: r);
824
825 return subject.intersected(r: clip).toFillPolygon().toPolygon();
826}
827
828/*!
829 \since 4.3
830
831 Returns a polygon which is \a r subtracted from this polygon.
832
833 Set operations on polygons will treat the polygons as
834 areas. Non-closed polygons will be treated as implicitly closed.
835
836*/
837
838QPolygon QPolygon::subtracted(const QPolygon &r) const
839{
840 QPainterPath subject; subject.addPolygon(polygon: *this);
841 QPainterPath clip; clip.addPolygon(polygon: r);
842
843 return subject.subtracted(r: clip).toFillPolygon().toPolygon();
844}
845
846/*!
847 \since 5.10
848
849 Returns \c true if the current polygon intersects at any point the given polygon \a p.
850 Also returns \c true if the current polygon contains or is contained by any part of \a p.
851
852 Set operations on polygons will treat the polygons as
853 areas. Non-closed polygons will be treated as implicitly closed.
854
855 \sa intersected()
856*/
857
858bool QPolygon::intersects(const QPolygon &p) const
859{
860 QPainterPath subject; subject.addPolygon(polygon: *this);
861 QPainterPath clip; clip.addPolygon(polygon: p);
862
863 return subject.intersects(p: clip);
864}
865
866/*!
867 \since 4.3
868
869 Returns a polygon which is the union of this polygon and \a r.
870
871 Set operations on polygons will treat the polygons as
872 areas. Non-closed polygons will be treated as implicitly closed.
873
874 \sa intersected(), subtracted()
875*/
876
877QPolygonF QPolygonF::united(const QPolygonF &r) const
878{
879 QPainterPath subject; subject.addPolygon(polygon: *this);
880 QPainterPath clip; clip.addPolygon(polygon: r);
881
882 return subject.united(r: clip).toFillPolygon();
883}
884
885/*!
886 \since 4.3
887
888 Returns a polygon which is the intersection of this polygon and \a r.
889
890 Set operations on polygons will treat the polygons as
891 areas. Non-closed polygons will be treated as implicitly closed.
892
893 \sa intersects()
894*/
895
896QPolygonF QPolygonF::intersected(const QPolygonF &r) const
897{
898 QPainterPath subject; subject.addPolygon(polygon: *this);
899 QPainterPath clip; clip.addPolygon(polygon: r);
900
901 return subject.intersected(r: clip).toFillPolygon();
902}
903
904/*!
905 \since 4.3
906
907 Returns a polygon which is \a r subtracted from this polygon.
908
909 Set operations on polygons will treat the polygons as
910 areas. Non-closed polygons will be treated as implicitly closed.
911
912*/
913
914QPolygonF QPolygonF::subtracted(const QPolygonF &r) const
915{
916 QPainterPath subject; subject.addPolygon(polygon: *this);
917 QPainterPath clip; clip.addPolygon(polygon: r);
918 return subject.subtracted(r: clip).toFillPolygon();
919}
920
921/*!
922 \since 5.10
923
924 Returns \c true if the current polygon intersects at any point the given polygon \a p.
925 Also returns \c true if the current polygon contains or is contained by any part of \a p.
926
927 Set operations on polygons will treat the polygons as
928 areas. Non-closed polygons will be treated as implicitly closed.
929
930 \sa intersected()
931*/
932
933bool QPolygonF::intersects(const QPolygonF &p) const
934{
935 QPainterPath subject; subject.addPolygon(polygon: *this);
936 QPainterPath clip; clip.addPolygon(polygon: p);
937
938 return subject.intersects(p: clip);
939}
940
941/*!
942 Returns the polygon as a QVariant.
943*/
944
945QPolygonF::operator QVariant() const
946{
947 return QVariant::fromValue(value: *this);
948}
949
950QT_END_NAMESPACE
951

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