Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qpolygon.cpp
Go to the documentation of this file.
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
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(y1, 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
88/*****************************************************************************
89 QPolygon member functions
90 *****************************************************************************/
91
123QPolygon::QPolygon(const QRect &r, bool closed)
124{
125 reserve(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
142QPolygon::QPolygon(int nPoints, const int *points)
143{
144 setPoints(nPoints, points);
145}
146
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
182QPolygon QPolygon::translated(int dx, int dy) const
183{
184 QPolygon copy(*this);
185 copy.translate(dx, dy);
186 return copy;
187}
188
206void QPolygon::point(int index, int *x, int *y) const
207{
208 QPoint p = at(index);
209 if (x)
210 *x = (int)p.x();
211 if (y)
212 *y = (int)p.y();
213}
214
235void QPolygon::setPoint(int index, int x, int y)
236{
237 (*this)[index] = QPoint(x, y);
238}
239
240
253void QPolygon::setPoints(int nPoints, const int *points)
254{
255 resize(nPoints);
256 int i = 0;
257 while (nPoints--) {
258 setPoint(i++, *points, *(points+1));
259 points += 2;
260 }
261}
262
277void QPolygon::setPoints(int nPoints, int firstx, int firsty, ...)
278{
279 va_list ap;
280 resize(nPoints);
281 setPoint(0, firstx, 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(++i, x, y);
288 }
289 va_end(ap);
290}
291
303void QPolygon::putPoints(int index, int nPoints, const int *points)
304{
305 if (index + nPoints > size())
306 resize(index + nPoints);
307 int i = index;
308 while (nPoints--) {
309 setPoint(i++, *points, *(points+1));
310 points += 2;
311 }
312}
313
335void QPolygon::putPoints(int index, int nPoints, int firstx, int firsty, ...)
336{
337 va_list ap;
338 if (index + nPoints > size())
339 resize(index + nPoints);
340 if (nPoints <= 0)
341 return;
342 setPoint(index, firstx, 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(++i, x, y);
349 }
350 va_end(ap);
351}
352
353
365void QPolygon::putPoints(int index, int nPoints, const QPolygon & from, int fromIndex)
366{
367 if (index + nPoints > size())
368 resize(index + nPoints);
369 if (nPoints <= 0)
370 return;
371 int n = 0;
372 while(n < nPoints) {
373 setPoint(index + n, from[fromIndex+n]);
374 ++n;
375 }
376}
377
378
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
419#ifndef QT_NO_DEBUG_STREAM
421{
422 QDebugStateSaver saver(dbg);
423 dbg.nospace() << "QPolygon(";
424 for (int i = 0; i < a.size(); ++i)
425 dbg.nospace() << a.at(i);
426 dbg.nospace() << ')';
427 return dbg;
428}
429#endif
430
431
465/*****************************************************************************
466 QPolygonF member functions
467 *****************************************************************************/
468
495{
496 reserve(5);
497 append(QPointF(r.x(), r.y()));
498 append(QPointF(r.x() + r.width(), r.y()));
499 append(QPointF(r.x() + r.width(), r.y() + r.height()));
500 append(QPointF(r.x(), r.y() + r.height()));
501 append(QPointF(r.x(), r.y()));
502}
503
514{
515 reserve(a.size());
516 for (int i=0; i<a.size(); ++i)
517 append(a.at(i));
518}
519
527{
528 if (offset.isNull())
529 return;
530
531 QPointF *p = data();
532 int i = size();
533 while (i--) {
534 *p += offset;
535 ++p;
536 }
537}
538
555{
556 QPolygonF copy(*this);
557 copy.translate(offset);
558 return copy;
559}
560
589{
590 const QPointF *pd = constData();
591 const QPointF *pe = pd + size();
592 if (pd == pe)
593 return QRectF(0, 0, 0, 0);
594 qreal minx, maxx, miny, maxy;
595 minx = maxx = pd->x();
596 miny = maxy = pd->y();
597 ++pd;
598 while (pd != pe) {
599 if (pd->x() < minx)
600 minx = pd->x();
601 else if (pd->x() > maxx)
602 maxx = pd->x();
603 if (pd->y() < miny)
604 miny = pd->y();
605 else if (pd->y() > maxy)
606 maxy = pd->y();
607 ++pd;
608 }
609 return QRectF(minx,miny, maxx - minx, maxy - miny);
610}
611
620{
621 QPolygon a;
622 a.reserve(size());
623 for (int i=0; i<size(); ++i)
624 a.append(at(i).toPoint());
625 return a;
626}
627
647QPolygon::operator QVariant() const
648{
649 return QVariant::fromValue(*this);
650}
651
652/*****************************************************************************
653 QPolygon stream functions
654 *****************************************************************************/
655#ifndef QT_NO_DATASTREAM
667{
668 const QList<QPoint> &v = a;
669 return s << v;
670}
671
683{
684 QList<QPoint> &v = a;
685 return s >> v;
686}
687#endif // QT_NO_DATASTREAM
688
689/*****************************************************************************
690 QPolygonF stream functions
691 *****************************************************************************/
692#ifndef QT_NO_DATASTREAM
704{
705 quint32 len = a.size();
706 uint i;
707
708 s << len;
709 for (i = 0; i < len; ++i)
710 s << a.at(i);
711 return s;
712}
713
725{
726 quint32 len;
727 uint i;
728
729 s >> len;
730 a.reserve(a.size() + (int)len);
731 QPointF p;
732 for (i = 0; i < len; ++i) {
733 s >> p;
734 a.insert(i, p);
735 }
736 return s;
737}
738#endif //QT_NO_DATASTREAM
739
740#ifndef QT_NO_DEBUG_STREAM
742{
743 QDebugStateSaver saver(dbg);
744 dbg.nospace() << "QPolygonF(";
745 for (int i = 0; i < a.size(); ++i)
746 dbg.nospace() << a.at(i);
747 dbg.nospace() << ')';
748 return dbg;
749}
750#endif
751
752
761bool QPolygonF::containsPoint(const QPointF &pt, Qt::FillRule fillRule) const
762{
763 if (isEmpty())
764 return false;
765
766 int winding_number = 0;
767
768 QPointF last_pt = at(0);
769 QPointF last_start = at(0);
770 for (int i = 1; i < size(); ++i) {
771 const QPointF &e = at(i);
772 qt_polygon_isect_line(last_pt, e, pt, &winding_number);
773 last_pt = e;
774 }
775
776 // implicitly close last subpath
777 if (last_pt != last_start)
778 qt_polygon_isect_line(last_pt, last_start, pt, &winding_number);
779
780 return (fillRule == Qt::WindingFill
781 ? (winding_number != 0)
782 : ((winding_number % 2) != 0));
783}
784
792bool QPolygon::containsPoint(const QPoint &pt, Qt::FillRule fillRule) const
793{
794 if (isEmpty())
795 return false;
796
797 int winding_number = 0;
798
799 QPoint last_pt = at(0);
800 QPoint last_start = at(0);
801 for (int i = 1; i < size(); ++i) {
802 const QPoint &e = at(i);
803 qt_polygon_isect_line(last_pt, e, pt, &winding_number);
804 last_pt = e;
805 }
806
807 // implicitly close last subpath
808 if (last_pt != last_start)
809 qt_polygon_isect_line(last_pt, last_start, pt, &winding_number);
810
811 return (fillRule == Qt::WindingFill
812 ? (winding_number != 0)
813 : ((winding_number % 2) != 0));
814}
815
828{
829 QPainterPath subject; subject.addPolygon(*this);
830 QPainterPath clip; clip.addPolygon(r);
831
832 return subject.united(clip).toFillPolygon().toPolygon();
833}
834
847{
848 QPainterPath subject; subject.addPolygon(*this);
849 QPainterPath clip; clip.addPolygon(r);
850
851 return subject.intersected(clip).toFillPolygon().toPolygon();
852}
853
865{
866 QPainterPath subject; subject.addPolygon(*this);
867 QPainterPath clip; clip.addPolygon(r);
868
869 return subject.subtracted(clip).toFillPolygon().toPolygon();
870}
871
885{
886 QPainterPath subject; subject.addPolygon(*this);
887 QPainterPath clip; clip.addPolygon(p);
888
889 return subject.intersects(clip);
890}
891
904{
905 QPainterPath subject; subject.addPolygon(*this);
906 QPainterPath clip; clip.addPolygon(r);
907
908 return subject.united(clip).toFillPolygon();
909}
910
923{
924 QPainterPath subject; subject.addPolygon(*this);
925 QPainterPath clip; clip.addPolygon(r);
926
927 return subject.intersected(clip).toFillPolygon();
928}
929
941{
942 QPainterPath subject; subject.addPolygon(*this);
943 QPainterPath clip; clip.addPolygon(r);
944 return subject.subtracted(clip).toFillPolygon();
945}
946
960{
961 QPainterPath subject; subject.addPolygon(*this);
962 QPainterPath clip; clip.addPolygon(p);
963
964 return subject.intersects(clip);
965}
966
971QPolygonF::operator QVariant() const
972{
973 return QVariant::fromValue(*this);
974}
975
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\inmodule QtCore
\inmodule QtCore
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
const_pointer constData() const noexcept
Definition qlist.h:416
bool isEmpty() const noexcept
Definition qlist.h:390
void reserve(qsizetype size)
Definition qlist.h:746
pointer data()
Definition qlist.h:414
void resize(qsizetype size)
Definition qlist.h:392
void append(parameter_type t)
Definition qlist.h:441
\inmodule QtGui
QPainterPath subtracted(const QPainterPath &r) const
void addPolygon(const QPolygonF &polygon)
Adds the given polygon to the path as an (unclosed) subpath.
QPolygonF toFillPolygon(const QTransform &matrix=QTransform()) const
Converts the path into a polygon using the QTransform matrix, and returns the polygon.
bool intersects(const QRectF &rect) const
Returns true if any point in the given rectangle intersects the path; otherwise returns false.
QPainterPath united(const QPainterPath &r) const
QPainterPath intersected(const QPainterPath &r) const
\inmodule QtCore\reentrant
Definition qpoint.h:214
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:333
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:338
\inmodule QtCore\reentrant
Definition qpoint.h:23
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:127
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:132
The QPolygonF class provides a list of points using floating point precision.
Definition qpolygon.h:96
QPolygon Q_GUI_EXPORT toPolygon() const
Creates and returns a QPolygon by converting each QPointF to a QPoint.
Definition qpolygon.cpp:619
Q_GUI_EXPORT QPolygonF intersected(const QPolygonF &r) const
Definition qpolygon.cpp:922
Q_GUI_EXPORT bool containsPoint(const QPointF &pt, Qt::FillRule fillRule) const
Definition qpolygon.cpp:761
Q_GUI_EXPORT QPolygonF subtracted(const QPolygonF &r) const
Definition qpolygon.cpp:940
Q_GUI_EXPORT QPolygonF united(const QPolygonF &r) const
Definition qpolygon.cpp:903
Q_GUI_EXPORT bool intersects(const QPolygonF &r) const
Definition qpolygon.cpp:959
void translate(qreal dx, qreal dy)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qpolygon.h:144
QPolygonF()=default
Constructs a polygon with no points.
QRectF Q_GUI_EXPORT boundingRect() const
Returns the bounding rectangle of the polygon, or QRectF(0,0,0,0) if the polygon is empty.
Definition qpolygon.cpp:588
QPolygonF translated(qreal dx, qreal dy) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qpolygon.h:147
The QPolygon class provides a list of points using integer precision.
Definition qpolygon.h:23
Q_GUI_EXPORT bool intersects(const QPolygon &r) const
Definition qpolygon.cpp:884
Q_GUI_EXPORT QPolygon subtracted(const QPolygon &r) const
Definition qpolygon.cpp:864
Q_GUI_EXPORT void translate(int dx, int dy)
Translates all points in the polygon by ({dx}, {dy}).
Definition qpolygon.cpp:153
QPolygon()=default
Constructs a polygon with no points.
Q_GUI_EXPORT QPolygon translated(int dx, int dy) const
Returns a copy of the polygon that is translated by ({dx}, {dy}).
Definition qpolygon.cpp:182
Q_GUI_EXPORT bool containsPoint(const QPoint &pt, Qt::FillRule fillRule) const
Definition qpolygon.cpp:792
Q_GUI_EXPORT void putPoints(int index, int nPoints, const int *points)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qpolygon.cpp:303
Q_GUI_EXPORT QPolygon united(const QPolygon &r) const
Definition qpolygon.cpp:827
Q_GUI_EXPORT void setPoint(int index, int x, int y)
Sets the point at the given index to the point specified by ({x}, {y}).
Definition qpolygon.cpp:235
Q_GUI_EXPORT QRect boundingRect() const
Returns the bounding rectangle of the polygon, or QRect(0, 0, 0, 0) if the polygon is empty.
Definition qpolygon.cpp:386
Q_GUI_EXPORT void point(int i, int *x, int *y) const
Extracts the coordinates of the point at the given index to {x} and *{y} (if they are valid pointers)...
Definition qpolygon.cpp:206
Q_GUI_EXPORT QPolygon intersected(const QPolygon &r) const
Definition qpolygon.cpp:846
Q_GUI_EXPORT void setPoints(int nPoints, const int *points)
Resizes the polygon to nPoints and populates it with the given points.
Definition qpolygon.cpp:253
\inmodule QtCore\reentrant
Definition qrect.h:483
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qvariant.h:64
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:531
QPixmap p2
QPixmap p1
[0]
double e
Combined button and popup list for selecting options.
@ WindingFill
static jboolean copy(JNIEnv *, jobject)
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:287
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLuint index
[2]
GLboolean r
[2]
GLuint GLfloat GLfloat GLfloat x1
GLenum GLuint GLintptr offset
GLfloat n
GLint y
GLfixed GLfixed GLint GLint GLfixed points
GLfixed GLfixed GLfixed y2
GLenum GLsizei len
GLfixed GLfixed x2
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
QDataStream & operator>>(QDataStream &s, QPolygon &a)
Definition qpolygon.cpp:682
static QT_BEGIN_NAMESPACE void qt_polygon_isect_line(const QPointF &p1, const QPointF &p2, const QPointF &pos, int *winding)
Definition qpolygon.cpp:19
QDebug operator<<(QDebug dbg, const QPolygon &a)
Definition qpolygon.cpp:420
unsigned int quint32
Definition qtypes.h:45
unsigned int uint
Definition qtypes.h:29
double qreal
Definition qtypes.h:92
QString dir
[11]
QAction * at