Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qpolygonclipper_p.h
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#ifndef QPOLYGONCLIPPER_P_H
5#define QPOLYGONCLIPPER_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists for the convenience
12// of other Qt classes. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/qrect.h>
19#include <QtGui/private/qdatabuffer_p.h>
20
22
23/* based on sutherland-hodgman line-by-line clipping, as described in
24 Computer Graphics and Principles */
25template <typename InType, typename OutType, typename CastType> class QPolygonClipper
26{
27public:
29 buffer1(0), buffer2(0)
30 {
31 x1 = y1 = x2 = y2 = 0;
32 }
33
35 {
36 }
37
38 void setBoundingRect(const QRect bounds)
39 {
40 x1 = bounds.x();
41 x2 = bounds.x() + bounds.width();
42 y1 = bounds.y();
43 y2 = bounds.y() + bounds.height();
44 }
45
47 {
48 return QRect(QPoint(x1, y1), QPoint(x2, y2));
49 }
50
51 inline OutType intersectLeft(const OutType &p1, const OutType &p2)
52 {
53 OutType t;
54 qreal dy = (p1.y - p2.y) / qreal(p1.x - p2.x);
55 t.x = x1;
56 t.y = static_cast<CastType>(p2.y + (x1 - p2.x) * dy);
57 return t;
58 }
59
60
61 inline OutType intersectRight(const OutType &p1, const OutType &p2)
62 {
63 OutType t;
64 qreal dy = (p1.y - p2.y) / qreal(p1.x - p2.x);
65 t.x = x2;
66 t.y = static_cast<CastType>(p2.y + (x2 - p2.x) * dy);
67 return t;
68 }
69
70
71 inline OutType intersectTop(const OutType &p1, const OutType &p2)
72 {
73 OutType t;
74 qreal dx = (p1.x - p2.x) / qreal(p1.y - p2.y);
75 t.x = static_cast<CastType>(p2.x + (y1 - p2.y) * dx);
76 t.y = y1;
77 return t;
78 }
79
80
81 inline OutType intersectBottom(const OutType &p1, const OutType &p2)
82 {
83 OutType t;
84 qreal dx = (p1.x - p2.x) / qreal(p1.y - p2.y);
85 t.x = static_cast<CastType>(p2.x + (y2 - p2.y) * dx);
86 t.y = y2;
87 return t;
88 }
89
90
91 void clipPolygon(const InType *inPoints, int inCount, OutType **outPoints, int *outCount,
92 bool closePolygon = true)
93 {
94 Q_ASSERT(outPoints);
95 Q_ASSERT(outCount);
96
97 if (inCount < 2) {
98 *outCount = 0;
99 return;
100 }
101
102 buffer1.reset();
103 buffer2.reset();
104
105 QDataBuffer<OutType> *source = &buffer1;
106 QDataBuffer<OutType> *clipped = &buffer2;
107
108 // Gather some info since we are iterating through the points anyway..
109 bool doLeft = false, doRight = false, doTop = false, doBottom = false;
110 OutType ot;
111 for (int i=0; i<inCount; ++i) {
112 ot = inPoints[i];
113 clipped->add(ot);
114
115 if (ot.x < x1)
116 doLeft = true;
117 else if (ot.x > x2)
118 doRight = true;
119 if (ot.y < y1)
120 doTop = true;
121 else if (ot.y > y2)
122 doBottom = true;
123 }
124
125 if (doLeft && clipped->size() > 1) {
126 QDataBuffer<OutType> *tmp = source;
127 source = clipped;
128 clipped = tmp;
129 clipped->reset();
130 int lastPos, start;
131 if (closePolygon) {
132 lastPos = source->size() - 1;
133 start = 0;
134 } else {
135 lastPos = 0;
136 start = 1;
137 if (source->at(0).x >= x1)
138 clipped->add(source->at(0));
139 }
140 for (int i=start; i<inCount; ++i) {
141 const OutType &cpt = source->at(i);
142 const OutType &ppt = source->at(lastPos);
143
144 if (cpt.x >= x1) {
145 if (ppt.x >= x1) {
146 clipped->add(cpt);
147 } else {
148 clipped->add(intersectLeft(cpt, ppt));
149 clipped->add(cpt);
150 }
151 } else if (ppt.x >= x1) {
152 clipped->add(intersectLeft(cpt, ppt));
153 }
154 lastPos = i;
155 }
156 }
157
158 if (doRight && clipped->size() > 1) {
159 QDataBuffer<OutType> *tmp = source;
160 source = clipped;
161 clipped = tmp;
162 clipped->reset();
163 int lastPos, start;
164 if (closePolygon) {
165 lastPos = source->size() - 1;
166 start = 0;
167 } else {
168 lastPos = 0;
169 start = 1;
170 if (source->at(0).x <= x2)
171 clipped->add(source->at(0));
172 }
173 for (int i=start; i<source->size(); ++i) {
174 const OutType &cpt = source->at(i);
175 const OutType &ppt = source->at(lastPos);
176
177 if (cpt.x <= x2) {
178 if (ppt.x <= x2) {
179 clipped->add(cpt);
180 } else {
181 clipped->add(intersectRight(cpt, ppt));
182 clipped->add(cpt);
183 }
184 } else if (ppt.x <= x2) {
185 clipped->add(intersectRight(cpt, ppt));
186 }
187
188 lastPos = i;
189 }
190
191 }
192
193 if (doTop && clipped->size() > 1) {
194 QDataBuffer<OutType> *tmp = source;
195 source = clipped;
196 clipped = tmp;
197 clipped->reset();
198 int lastPos, start;
199 if (closePolygon) {
200 lastPos = source->size() - 1;
201 start = 0;
202 } else {
203 lastPos = 0;
204 start = 1;
205 if (source->at(0).y >= y1)
206 clipped->add(source->at(0));
207 }
208 for (int i=start; i<source->size(); ++i) {
209 const OutType &cpt = source->at(i);
210 const OutType &ppt = source->at(lastPos);
211
212 if (cpt.y >= y1) {
213 if (ppt.y >= y1) {
214 clipped->add(cpt);
215 } else {
216 clipped->add(intersectTop(cpt, ppt));
217 clipped->add(cpt);
218 }
219 } else if (ppt.y >= y1) {
220 clipped->add(intersectTop(cpt, ppt));
221 }
222
223 lastPos = i;
224 }
225 }
226
227 if (doBottom && clipped->size() > 1) {
228 QDataBuffer<OutType> *tmp = source;
229 source = clipped;
230 clipped = tmp;
231 clipped->reset();
232 int lastPos, start;
233 if (closePolygon) {
234 lastPos = source->size() - 1;
235 start = 0;
236 } else {
237 lastPos = 0;
238 start = 1;
239 if (source->at(0).y <= y2)
240 clipped->add(source->at(0));
241 }
242 for (int i=start; i<source->size(); ++i) {
243 const OutType &cpt = source->at(i);
244 const OutType &ppt = source->at(lastPos);
245
246 if (cpt.y <= y2) {
247 if (ppt.y <= y2) {
248 clipped->add(cpt);
249 } else {
250 clipped->add(intersectBottom(cpt, ppt));
251 clipped->add(cpt);
252 }
253 } else if (ppt.y <= y2) {
254 clipped->add(intersectBottom(cpt, ppt));
255 }
256 lastPos = i;
257 }
258 }
259
260 if (closePolygon && clipped->size() > 0) {
261 // close clipped polygon
262 if (clipped->at(0).x != clipped->at(clipped->size()-1).x ||
263 clipped->at(0).y != clipped->at(clipped->size()-1).y) {
264 OutType ot = clipped->at(0);
265 clipped->add(ot);
266 }
267 }
268 *outCount = clipped->size();
269 *outPoints = clipped->data();
270 }
271
272private:
273 int x1, x2, y1, y2;
274 QDataBuffer<OutType> buffer1;
275 QDataBuffer<OutType> buffer2;
276};
277
279
280#endif // QPOLYGONCLIPPER_P_H
void add(const Type &t)
\inmodule QtCore\reentrant
Definition qpoint.h:25
OutType intersectTop(const OutType &p1, const OutType &p2)
OutType intersectBottom(const OutType &p1, const OutType &p2)
void setBoundingRect(const QRect bounds)
OutType intersectRight(const OutType &p1, const OutType &p2)
OutType intersectLeft(const OutType &p1, const OutType &p2)
void clipPolygon(const InType *inPoints, int inCount, OutType **outPoints, int *outCount, bool closePolygon=true)
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:185
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:188
QPixmap p2
QPixmap p1
[0]
Combined button and popup list for selecting options.
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLuint GLfloat GLfloat GLfloat x1
GLuint start
GLsizei GLsizei GLchar * source
GLfixed GLfixed GLfixed y2
GLfixed GLfixed x2
GLdouble GLdouble t
Definition qopenglext.h:243
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
double qreal
Definition qtypes.h:187