15 static int col(
const QRect &rc) {
19 return rc.x() + rc.width();
24 static bool rowIsLess(
const QRect &lhs,
const QRect &rhs) {
25 return lhs.y() < rhs.y();
28 return lhs.y() < rhs.y() || (lhs.y() == rhs.y() && lhs.x() < rhs.x());
34 static int col(
const QRect &rc) {
38 return rc.y() + rc.height();
43 static bool rowIsLess(
const QRect &lhs,
const QRect &rhs) {
44 return lhs.x() < rhs.x();
47 return lhs.x() < rhs.x() || (lhs.x() == rhs.x() && lhs.y() < rhs.y());
51template <
typename MergePolicy>
56 if (beginIt == endIt)
return endIt;
58 std::sort(beginIt, endIt, MergePolicy::elementIsLess);
60 auto resultIt = beginIt;
61 auto it = std::next(beginIt);
64 auto rowEnd = std::upper_bound(it, endIt, *it, MergePolicy::rowIsLess);
65 for (
auto rowIt = it; rowIt != rowEnd; ++rowIt) {
66 if (policy.rowHeight(*resultIt) == policy.rowHeight(*rowIt) &&
67 policy.nextCol(*resultIt) == policy.col(*rowIt)) {
78 return std::next(resultIt);
93 return rc.setBottom(
rowEnd);
95 static bool rowIsLess(
const QRect &lhs,
const QRect &rhs) {
96 return lhs.y() < rhs.y();
99 return QRect(rc.x(), rc.y(),
100 rc.width(),
rowEnd - rc.y() + 1);
103 return QRect(rc.x(),
rowEnd + 1,
104 rc.width(), rc.height() - (
rowEnd - rc.y() + 1));
120 return rc.setRight(
rowEnd);
122 static bool rowIsLess(
const QRect &lhs,
const QRect &rhs) {
123 return lhs.x() < rhs.x();
126 return QRect(rc.x(), rc.y(),
127 rowEnd - rc.x() + 1, rc.height());
130 return QRect(
rowEnd + 1, rc.y(),
131 rc.width() - (
rowEnd - rc.x() + 1), rc.height());
138 template<
typename P1,
typename... Params>
155 QRect(), std::bit_or<QRect>()));
164template <
typename Policy,
typename RowMergeOp,
typename OutIt>
169 RowMergeOp rowMergeOp)
171 if (beginIt == endIt)
return;
176 std::sort(beginIt, endIt, Policy::rowIsLess);
177 int rowStart = Policy::rowStart(*beginIt);
178 int rowEnd = rowStart + gridSize - 1;
182 bool switchToNextRow =
false;
185 if (nextRowExtra.isEmpty()) {
189 switchToNextRow =
true;
191 }
else if (Policy::rowStart(*it) > rowEnd) {
192 switchToNextRow =
true;
195 if (switchToNextRow) {
198 if (!nextRowExtra.isEmpty()) {
199 rowStart = Policy::rowStart(nextRowExtra.first());
200 rowEnd = rowStart + gridSize - 1;
202 for (
auto nextIt = nextRowExtra.begin(); nextIt != nextRowExtra.end(); ++nextIt) {
203 if (Policy::rowEnd(*nextIt) > rowEnd) {
204 nextRowExtraTmp.append(Policy::splitRectLo(*nextIt, rowEnd));
205 *resultIt++ = Policy::splitRectHi(*nextIt, rowEnd);
207 *resultIt++ = *nextIt;
210 nextRowExtra.clear();
211 std::swap(nextRowExtra, nextRowExtraTmp);
215 rowStart = Policy::rowStart(*it);
216 rowEnd = rowStart + gridSize - 1;
220 if (Policy::rowEnd(*it) > rowEnd) {
221 nextRowExtra.append(Policy::splitRectLo(*it, rowEnd));
222 *resultIt++ = Policy::splitRectHi(*it, rowEnd);
244 if (
rects.isEmpty())
return;
250 splitRects<VerticalSplitPolicy>(
rects.begin(),
rects.end(),
251 std::back_inserter(rowsBuf),
258 auto rowBegin = rowsBuf.begin();
259 while (rowBegin != rowsBuf.end()) {
260 auto rowEnd = std::upper_bound(rowBegin, rowsBuf.end(),
262 rowBegin->y() + gridSize - 1,
264 VerticalSplitPolicy::rowIsLess);
266 splitRects<HorizontalSplitPolicy>(rowBegin, rowEnd,
267 std::back_inserter(intermediate),
281 auto it = std::unique(
rects.begin(),
rects.end());
329 return std::accumulate(
m_rects.constBegin(),
m_rects.constEnd(), QRect(), std::bit_or<QRect>());
356 return std::accumulate(
m_rects.constBegin(),
m_rects.constEnd(), QRegion(), std::bit_or<QRegion>());
363 [dx, dy] (
const QRect &rc) { return rc.translated(dx, dy); });
377 QRegion::const_iterator begin = region.begin();
378 while (begin != region.end()) {
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
bool operator==(const KisRegion &lhs, const KisRegion &rhs)
static KisRegion fromQRegion(const QRegion ®ion)
KisRegion translated(int x, int y) const
static KisRegion fromOverlappingRects(const QVector< QRect > &rects, int gridSize)
QRect boundingRect() const
KisRegion & operator=(const KisRegion &rhs)
static QVector< QRect >::iterator mergeSparseRects(QVector< QRect >::iterator beginIt, QVector< QRect >::iterator endIt)
merge a set of rectangles into a smaller set of bigger rectangles
void translate(int dx, int dy)
QVector< QRect > rects() const
static void makeGridLikeRectsUnique(QVector< QRect > &rects)
KisRegion & operator&=(const QRect &rect)
static void approximateOverlappingRects(QVector< QRect > &rects, int gridSize)
QRegion toQRegion() const
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
QVector< QRect >::iterator mergeRects(QVector< QRect >::iterator beginIt, QVector< QRect >::iterator endIt, MergePolicy policy)
void splitRects(QVector< QRect >::iterator beginIt, QVector< QRect >::iterator endIt, OutIt resultIt, QVector< QRect > tempBuf[2], int gridSize, RowMergeOp rowMergeOp)
static bool elementIsLess(const QRect &lhs, const QRect &rhs)
static int col(const QRect &rc)
static int nextCol(const QRect &rc)
static bool rowIsLess(const QRect &lhs, const QRect &rhs)
static int rowHeight(const QRect &rc)
static QRect splitRectHi(const QRect &rc, int rowEnd)
static bool rowIsLess(const QRect &lhs, const QRect &rhs)
static void setRowEnd(QRect &rc, int rowEnd)
static QRect splitRectLo(const QRect &rc, int rowEnd)
static int rowEnd(const QRect &rc)
static int rowStart(const QRect &rc)
static int rowHeight(const QRect &rc)
QVector< QRect > & m_destination
MergeRectsOp(QVector< QRect > &source, QVector< QRect > &destination)
QVector< QRect > & m_source
static int nextCol(const QRect &rc)
static int col(const QRect &rc)
static int rowHeight(const QRect &rc)
static bool rowIsLess(const QRect &lhs, const QRect &rhs)
static bool elementIsLess(const QRect &lhs, const QRect &rhs)
static bool rowIsLess(const QRect &lhs, const QRect &rhs)
static void setRowEnd(QRect &rc, int rowEnd)
static int rowHeight(const QRect &rc)
static QRect splitRectHi(const QRect &rc, int rowEnd)
static QRect splitRectLo(const QRect &rc, int rowEnd)
static int rowEnd(const QRect &rc)
static int rowStart(const QRect &rc)
void operator()(P1 p1, Params... parameters)