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