1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the painting module of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29
#ifndef QPOLYGONCLIPPER_P_H
30
#define QPOLYGONCLIPPER_P_H
36
// This file is not part of the Qt API. It exists for the convenience
37
// of other Qt classes. This header file may change from version to
38
// version without notice, or even be removed.
43
#include "qdatabuffer_p.h"
45
/* based on sutherland-hodgman line-by-line clipping, as described in
46
Computer Graphics and Principles */
47
template <typename InType, typename OutType, typename CastType> class QPolygonClipper
52
x1 = y1 = x2 = y2 = 0;
59
void setBoundingRect(const QRect bounds)
62
x2 = bounds.x() + bounds.width();
64
y2 = bounds.y() + bounds.height();
69
return QRect(QPoint(x1, y1), QPoint(x2, y2));
72
inline OutType intersectLeft(const OutType &p1, const OutType &p2)
75
double dy = (p1.y - p2.y) / double(p1.x - p2.x);
77
t.y = static_cast<CastType>(p2.y + (x1 - p2.x) * dy);
82
inline OutType intersectRight(const OutType &p1, const OutType &p2)
85
double dy = (p1.y - p2.y) / double(p1.x - p2.x);
87
t.y = static_cast<CastType>(p2.y + (x2 - p2.x) * dy);
92
inline OutType intersectTop(const OutType &p1, const OutType &p2)
95
double dx = (p1.x - p2.x) / double(p1.y - p2.y);
96
t.x = static_cast<CastType>(p2.x + (y1 - p2.y) * dx);
102
inline OutType intersectBottom(const OutType &p1, const OutType &p2)
105
double dx = (p1.x - p2.x) / double(p1.y - p2.y);
106
t.x = static_cast<CastType>(p2.x + (y2 - p2.y) * dx);
112
void clipPolygon(const InType *inPoints, int inCount, OutType **outPoints, int *outCount,
113
bool closePolygon = true)
126
QDataBuffer<OutType> *source = &buffer1;
127
QDataBuffer<OutType> *clipped = &buffer2;
129
// Gather some info since we are iterating through the points anyway..
130
bool doLeft = false, doRight = false, doTop = false, doBottom = false;
132
for (int i=0; i<inCount; ++i) {
146
if (doLeft && clipped->size() > 1) {
147
QDataBuffer<OutType> *tmp = source;
153
lastPos = source->size() - 1;
158
if (source->at(0).x >= x1)
159
clipped->add(source->at(0));
161
for (int i=start; i<inCount; ++i) {
162
const OutType &cpt = source->at(i);
163
const OutType &ppt = source->at(lastPos);
169
clipped->add(intersectLeft(cpt, ppt));
172
} else if (ppt.x >= x1) {
173
clipped->add(intersectLeft(cpt, ppt));
179
if (doRight && clipped->size() > 1) {
180
QDataBuffer<OutType> *tmp = source;
186
lastPos = source->size() - 1;
191
if (source->at(0).x <= x2)
192
clipped->add(source->at(0));
194
for (int i=start; i<source->size(); ++i) {
195
const OutType &cpt = source->at(i);
196
const OutType &ppt = source->at(lastPos);
202
clipped->add(intersectRight(cpt, ppt));
205
} else if (ppt.x <= x2) {
206
clipped->add(intersectRight(cpt, ppt));
214
if (doTop && clipped->size() > 1) {
215
QDataBuffer<OutType> *tmp = source;
221
lastPos = source->size() - 1;
226
if (source->at(0).y >= y1)
227
clipped->add(source->at(0));
229
for (int i=start; i<source->size(); ++i) {
230
const OutType &cpt = source->at(i);
231
const OutType &ppt = source->at(lastPos);
237
clipped->add(intersectTop(cpt, ppt));
240
} else if (ppt.y >= y1) {
241
clipped->add(intersectTop(cpt, ppt));
248
if (doBottom && clipped->size() > 1) {
249
QDataBuffer<OutType> *tmp = source;
255
lastPos = source->size() - 1;
260
if (source->at(0).y <= y2)
261
clipped->add(source->at(0));
263
for (int i=start; i<source->size(); ++i) {
264
const OutType &cpt = source->at(i);
265
const OutType &ppt = source->at(lastPos);
271
clipped->add(intersectBottom(cpt, ppt));
274
} else if (ppt.y <= y2) {
275
clipped->add(intersectBottom(cpt, ppt));
281
if (closePolygon && clipped->size() > 0) {
282
// close clipped polygon
283
if (clipped->at(0).x != clipped->at(clipped->size()-1).x ||
284
clipped->at(0).y != clipped->at(clipped->size()-1).y)
285
clipped->add(clipped->at(0));
287
*outCount = clipped->size();
288
*outPoints = clipped->data();
293
QDataBuffer<OutType> buffer1;
294
QDataBuffer<OutType> buffer2;
297
#endif // QPOLYGONCLIPPER_P_H