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 | |
16 | QT_BEGIN_NAMESPACE |
17 | |
18 | //same as qt_painterpath_isect_line in qpainterpath.cpp |
19 | static 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 | |
123 | QPolygon::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 | |
142 | QPolygon::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 | |
153 | void 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 | */ |
182 | QPolygon 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 | |
206 | void 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 | */ |
235 | void 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 | |
253 | void 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 | |
277 | void 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 | |
303 | void 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 | |
335 | void 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 | |
365 | void 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 | |
386 | QRect 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 |
420 | QDebug 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 | |
489 | QPolygonF::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 | |
508 | QPolygonF::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 | |
521 | void 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 | */ |
549 | QPolygonF 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 | |
583 | QRectF 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 | |
614 | QPolygon 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 | */ |
642 | QPolygon::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 | */ |
661 | QDataStream &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 | */ |
677 | QDataStream &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 | |
698 | QDataStream &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 | |
719 | QDataStream &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 |
736 | QDebug 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 | */ |
751 | bool 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 | */ |
782 | bool 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 | |
817 | QPolygon 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 | |
836 | QPolygon 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 | |
854 | QPolygon 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 | |
874 | bool 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 | |
893 | QPolygonF 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 | |
912 | QPolygonF 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 | |
930 | QPolygonF 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 | |
949 | bool 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 | |
961 | QPolygonF::operator QVariant() const |
962 | { |
963 | return QVariant::fromValue(value: *this); |
964 | } |
965 | |
966 | QT_END_NAMESPACE |
967 | |