QtBase  v6.3.1
qpolygon.cpp
Go to the documentation of this file.
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 
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(y1, 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 
124 /*****************************************************************************
125  QPolygon member functions
126  *****************************************************************************/
127 
159 QPolygon::QPolygon(const QRect &r, bool closed)
160 {
161  reserve(closed ? 5 : 4);
162  *this << QPoint(r.x(), r.y())
163  << QPoint(r.x() + r.width(), r.y())
164  << QPoint(r.x() + r.width(), r.y() + r.height())
165  << QPoint(r.x(), r.y() + r.height());
166  if (closed)
167  *this << QPoint(r.left(), r.top());
168 }
169 
178 QPolygon::QPolygon(int nPoints, const int *points)
179 {
180  setPoints(nPoints, points);
181 }
182 
189 void QPolygon::translate(int dx, int dy)
190 {
191  if (dx == 0 && dy == 0)
192  return;
193 
194  QPoint *p = data();
195  int i = size();
196  QPoint pt(dx, dy);
197  while (i--) {
198  *p += pt;
199  ++p;
200  }
201 }
202 
218 QPolygon QPolygon::translated(int dx, int dy) const
219 {
220  QPolygon copy(*this);
221  copy.translate(dx, dy);
222  return copy;
223 }
224 
242 void QPolygon::point(int index, int *x, int *y) const
243 {
244  QPoint p = at(index);
245  if (x)
246  *x = (int)p.x();
247  if (y)
248  *y = (int)p.y();
249 }
250 
271 void QPolygon::setPoint(int index, int x, int y)
272 {
273  (*this)[index] = QPoint(x, y);
274 }
275 
276 
289 void QPolygon::setPoints(int nPoints, const int *points)
290 {
291  resize(nPoints);
292  int i = 0;
293  while (nPoints--) {
294  setPoint(i++, *points, *(points+1));
295  points += 2;
296  }
297 }
298 
313 void QPolygon::setPoints(int nPoints, int firstx, int firsty, ...)
314 {
315  va_list ap;
316  resize(nPoints);
317  setPoint(0, firstx, firsty);
318  int i = 0, x, y;
319  va_start(ap, firsty);
320  while (--nPoints) {
321  x = va_arg(ap, int);
322  y = va_arg(ap, int);
323  setPoint(++i, x, y);
324  }
325  va_end(ap);
326 }
327 
339 void QPolygon::putPoints(int index, int nPoints, const int *points)
340 {
341  if (index + nPoints > size())
342  resize(index + nPoints);
343  int i = index;
344  while (nPoints--) {
345  setPoint(i++, *points, *(points+1));
346  points += 2;
347  }
348 }
349 
371 void QPolygon::putPoints(int index, int nPoints, int firstx, int firsty, ...)
372 {
373  va_list ap;
374  if (index + nPoints > size())
375  resize(index + nPoints);
376  if (nPoints <= 0)
377  return;
378  setPoint(index, firstx, firsty);
379  int i = index, x, y;
380  va_start(ap, firsty);
381  while (--nPoints) {
382  x = va_arg(ap, int);
383  y = va_arg(ap, int);
384  setPoint(++i, x, y);
385  }
386  va_end(ap);
387 }
388 
389 
401 void QPolygon::putPoints(int index, int nPoints, const QPolygon & from, int fromIndex)
402 {
403  if (index + nPoints > size())
404  resize(index + nPoints);
405  if (nPoints <= 0)
406  return;
407  int n = 0;
408  while(n < nPoints) {
409  setPoint(index + n, from[fromIndex+n]);
410  ++n;
411  }
412 }
413 
414 
423 {
424  const QPoint *pd = constData();
425  const QPoint *pe = pd + size();
426  if (pd == pe)
427  return QRect(0, 0, 0, 0);
428  int minx, maxx, miny, maxy;
429  minx = maxx = pd->x();
430  miny = maxy = pd->y();
431  ++pd;
432  for (; pd != pe; ++pd) {
433  if (pd->x() < minx)
434  minx = pd->x();
435  else if (pd->x() > maxx)
436  maxx = pd->x();
437  if (pd->y() < miny)
438  miny = pd->y();
439  else if (pd->y() > maxy)
440  maxy = pd->y();
441  }
442  return QRect(QPoint(minx,miny), QPoint(maxx,maxy));
443 }
444 
445 #ifndef QT_NO_DEBUG_STREAM
447 {
448  QDebugStateSaver saver(dbg);
449  dbg.nospace() << "QPolygon(";
450  for (int i = 0; i < a.count(); ++i)
451  dbg.nospace() << a.at(i);
452  dbg.nospace() << ')';
453  return dbg;
454 }
455 #endif
456 
457 
491 /*****************************************************************************
492  QPolygonF member functions
493  *****************************************************************************/
494 
521 {
522  reserve(5);
523  append(QPointF(r.x(), r.y()));
524  append(QPointF(r.x() + r.width(), r.y()));
525  append(QPointF(r.x() + r.width(), r.y() + r.height()));
526  append(QPointF(r.x(), r.y() + r.height()));
527  append(QPointF(r.x(), r.y()));
528 }
529 
540 {
541  reserve(a.size());
542  for (int i=0; i<a.size(); ++i)
543  append(a.at(i));
544 }
545 
553 {
554  if (offset.isNull())
555  return;
556 
557  QPointF *p = data();
558  int i = size();
559  while (i--) {
560  *p += offset;
561  ++p;
562  }
563 }
564 
581 {
582  QPolygonF copy(*this);
583  copy.translate(offset);
584  return copy;
585 }
586 
615 {
616  const QPointF *pd = constData();
617  const QPointF *pe = pd + size();
618  if (pd == pe)
619  return QRectF(0, 0, 0, 0);
620  qreal minx, maxx, miny, maxy;
621  minx = maxx = pd->x();
622  miny = maxy = pd->y();
623  ++pd;
624  while (pd != pe) {
625  if (pd->x() < minx)
626  minx = pd->x();
627  else if (pd->x() > maxx)
628  maxx = pd->x();
629  if (pd->y() < miny)
630  miny = pd->y();
631  else if (pd->y() > maxy)
632  maxy = pd->y();
633  ++pd;
634  }
635  return QRectF(minx,miny, maxx - minx, maxy - miny);
636 }
637 
646 {
647  QPolygon a;
648  a.reserve(size());
649  for (int i=0; i<size(); ++i)
650  a.append(at(i).toPoint());
651  return a;
652 }
653 
673 QPolygon::operator QVariant() const
674 {
675  return QVariant::fromValue(*this);
676 }
677 
678 /*****************************************************************************
679  QPolygon stream functions
680  *****************************************************************************/
681 #ifndef QT_NO_DATASTREAM
693 {
694  const QList<QPoint> &v = a;
695  return s << v;
696 }
697 
709 {
710  QList<QPoint> &v = a;
711  return s >> v;
712 }
713 #endif // QT_NO_DATASTREAM
714 
715 /*****************************************************************************
716  QPolygonF stream functions
717  *****************************************************************************/
718 #ifndef QT_NO_DATASTREAM
730 {
731  quint32 len = a.size();
732  uint i;
733 
734  s << len;
735  for (i = 0; i < len; ++i)
736  s << a.at(i);
737  return s;
738 }
739 
751 {
752  quint32 len;
753  uint i;
754 
755  s >> len;
756  a.reserve(a.size() + (int)len);
757  QPointF p;
758  for (i = 0; i < len; ++i) {
759  s >> p;
760  a.insert(i, p);
761  }
762  return s;
763 }
764 #endif //QT_NO_DATASTREAM
765 
766 #ifndef QT_NO_DEBUG_STREAM
768 {
769  QDebugStateSaver saver(dbg);
770  dbg.nospace() << "QPolygonF(";
771  for (int i = 0; i < a.count(); ++i)
772  dbg.nospace() << a.at(i);
773  dbg.nospace() << ')';
774  return dbg;
775 }
776 #endif
777 
778 
787 bool QPolygonF::containsPoint(const QPointF &pt, Qt::FillRule fillRule) const
788 {
789  if (isEmpty())
790  return false;
791 
792  int winding_number = 0;
793 
794  QPointF last_pt = at(0);
795  QPointF last_start = at(0);
796  for (int i = 1; i < size(); ++i) {
797  const QPointF &e = at(i);
798  qt_polygon_isect_line(last_pt, e, pt, &winding_number);
799  last_pt = e;
800  }
801 
802  // implicitly close last subpath
803  if (last_pt != last_start)
804  qt_polygon_isect_line(last_pt, last_start, pt, &winding_number);
805 
806  return (fillRule == Qt::WindingFill
807  ? (winding_number != 0)
808  : ((winding_number % 2) != 0));
809 }
810 
818 bool QPolygon::containsPoint(const QPoint &pt, Qt::FillRule fillRule) const
819 {
820  if (isEmpty())
821  return false;
822 
823  int winding_number = 0;
824 
825  QPoint last_pt = at(0);
826  QPoint last_start = at(0);
827  for (int i = 1; i < size(); ++i) {
828  const QPoint &e = at(i);
829  qt_polygon_isect_line(last_pt, e, pt, &winding_number);
830  last_pt = e;
831  }
832 
833  // implicitly close last subpath
834  if (last_pt != last_start)
835  qt_polygon_isect_line(last_pt, last_start, pt, &winding_number);
836 
837  return (fillRule == Qt::WindingFill
838  ? (winding_number != 0)
839  : ((winding_number % 2) != 0));
840 }
841 
854 {
855  QPainterPath subject; subject.addPolygon(*this);
856  QPainterPath clip; clip.addPolygon(r);
857 
858  return subject.united(clip).toFillPolygon().toPolygon();
859 }
860 
873 {
874  QPainterPath subject; subject.addPolygon(*this);
875  QPainterPath clip; clip.addPolygon(r);
876 
877  return subject.intersected(clip).toFillPolygon().toPolygon();
878 }
879 
891 {
892  QPainterPath subject; subject.addPolygon(*this);
893  QPainterPath clip; clip.addPolygon(r);
894 
895  return subject.subtracted(clip).toFillPolygon().toPolygon();
896 }
897 
910 bool QPolygon::intersects(const QPolygon &p) const
911 {
912  QPainterPath subject; subject.addPolygon(*this);
913  QPainterPath clip; clip.addPolygon(p);
914 
915  return subject.intersects(clip);
916 }
917 
930 {
931  QPainterPath subject; subject.addPolygon(*this);
932  QPainterPath clip; clip.addPolygon(r);
933 
934  return subject.united(clip).toFillPolygon();
935 }
936 
949 {
950  QPainterPath subject; subject.addPolygon(*this);
951  QPainterPath clip; clip.addPolygon(r);
952 
953  return subject.intersected(clip).toFillPolygon();
954 }
955 
967 {
968  QPainterPath subject; subject.addPolygon(*this);
969  QPainterPath clip; clip.addPolygon(r);
970  return subject.subtracted(clip).toFillPolygon();
971 }
972 
986 {
987  QPainterPath subject; subject.addPolygon(*this);
988  QPainterPath clip; clip.addPolygon(p);
989 
990  return subject.intersects(clip);
991 }
992 
997 QPolygonF::operator QVariant() const
998 {
999  return QVariant::fromValue(*this);
1000 }
1001 
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:66
operator>>(QDataStream &ds, qfloat16 &f)
Definition: qfloat16.cpp:344
operator<<(QDataStream &ds, qfloat16 f)
Definition: qfloat16.cpp:327
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:65
QDebug & nospace()
Definition: qdebug.h:113
Convenience class for custom QDebug operators.
Definition: qdebug.h:176
qsizetype size() const noexcept
Definition: qlist.h:414
const_pointer constData() const noexcept
Definition: qlist.h:444
bool isEmpty() const noexcept
Definition: qlist.h:418
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
void reserve(qsizetype size)
Definition: qlist.h:757
pointer data()
Definition: qlist.h:442
void resize(qsizetype size)
Definition: qlist.h:420
void append(parameter_type t)
Definition: qlist.h:469
bool qFuzzyCompare(const QMatrix4x4 &m1, const QMatrix4x4 &m2)
Definition: qmatrix4x4.cpp:774
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:65
QPainterPath subtracted(const QPainterPath &r) const
void addPolygon(const QPolygonF &polygon)
QPolygonF toFillPolygon(const QTransform &matrix=QTransform()) const
bool intersects(const QRectF &rect) const
QPainterPath united(const QPainterPath &r) const
QPainterPath intersected(const QPainterPath &r) const
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:242
constexpr qreal x() const noexcept
Definition: qpoint.h:361
constexpr qreal y() const noexcept
Definition: qpoint.h:366
constexpr QPoint toPoint() const
Definition: qpoint.h:420
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:52
constexpr int x() const noexcept
Definition: qpoint.h:155
constexpr int y() const noexcept
Definition: qpoint.h:160
The QPolygonF class provides a list of points using floating point precision. \inmodule QtGui.
Definition: qpolygon.h:128
QPolygon Q_GUI_EXPORT toPolygon() const
Definition: qpolygon.cpp:645
Q_GUI_EXPORT QPolygonF intersected(const QPolygonF &r) const
Definition: qpolygon.cpp:948
Q_GUI_EXPORT bool containsPoint(const QPointF &pt, Qt::FillRule fillRule) const
Definition: qpolygon.cpp:787
Q_GUI_EXPORT QPolygonF subtracted(const QPolygonF &r) const
Definition: qpolygon.cpp:966
Q_GUI_EXPORT QPolygonF united(const QPolygonF &r) const
Definition: qpolygon.cpp:929
Q_GUI_EXPORT bool intersects(const QPolygonF &r) const
Definition: qpolygon.cpp:985
void translate(qreal dx, qreal dy)
Definition: qpolygon.h:174
QPolygonF()=default
QRectF Q_GUI_EXPORT boundingRect() const
Definition: qpolygon.cpp:614
QPolygonF translated(qreal dx, qreal dy) const
Definition: qpolygon.h:177
The QPolygon class provides a list of points using integer precision. \inmodule QtGui.
Definition: qpolygon.h:57
Q_GUI_EXPORT bool intersects(const QPolygon &r) const
Definition: qpolygon.cpp:910
Q_GUI_EXPORT QPolygon subtracted(const QPolygon &r) const
Definition: qpolygon.cpp:890
Q_GUI_EXPORT void translate(int dx, int dy)
Definition: qpolygon.cpp:189
QPolygon()=default
Q_GUI_EXPORT QPolygon translated(int dx, int dy) const
Definition: qpolygon.cpp:218
Q_GUI_EXPORT bool containsPoint(const QPoint &pt, Qt::FillRule fillRule) const
Definition: qpolygon.cpp:818
Q_GUI_EXPORT void putPoints(int index, int nPoints, const int *points)
Definition: qpolygon.cpp:339
Q_GUI_EXPORT QPolygon united(const QPolygon &r) const
Definition: qpolygon.cpp:853
Q_GUI_EXPORT void setPoint(int index, int x, int y)
Definition: qpolygon.cpp:271
Q_GUI_EXPORT QRect boundingRect() const
Definition: qpolygon.cpp:422
Q_GUI_EXPORT void point(int i, int *x, int *y) const
Definition: qpolygon.cpp:242
Q_GUI_EXPORT QPolygon intersected(const QPolygon &r) const
Definition: qpolygon.cpp:872
Q_GUI_EXPORT void setPoints(int nPoints, const int *points)
Definition: qpolygon.cpp:289
The QRectF class defines a finite rectangle in the plane using floating point precision.
Definition: qrect.h:511
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:59
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
static auto fromValue(const T &value) -> std::enable_if_t< std::is_copy_constructible_v< T >, QVariant >
Definition: qvariant.h:391
QPixmap p2
QPixmap p1
[0]
double e
va_end(ap)
static void const void const char bool unsigned int int const char va_start(ap, message)
FillRule
Definition: qnamespace.h:1320
@ WindingFill
Definition: qnamespace.h:1322
unsigned int quint32
Definition: qglobal.h:288
QT_END_INCLUDE_NAMESPACE typedef double qreal
Definition: qglobal.h:341
unsigned int uint
Definition: qglobal.h:334
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLboolean r
[2]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLuint index
[2]
GLuint GLfloat GLfloat GLfloat x1
GLenum GLuint GLintptr offset
GLfloat n
GLint y
GLfixed GLfixed GLint GLint GLfixed points
Definition: qopenglext.h:5206
GLfixed GLfixed GLfixed y2
Definition: qopenglext.h:5231
GLenum GLsizei len
Definition: qopenglext.h:3292
GLfixed GLfixed x2
Definition: qopenglext.h:5231
GLdouble s
[6]
Definition: qopenglext.h:235
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
QString dir
[11]