00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #ifndef QVDISJOINTSET_H
00026 #define QVDISJOINTSET_H
00027
00028 #include <QVImage>
00029
00030 #define INDEX(Col, Row) (Row*cols + Col)
00031
00128 class QVDisjointSet
00129 {
00130 public:
00137 QVDisjointSet(uInt numElements);
00138
00154 QVDisjointSet(uInt cols, uInt rows);
00155
00169 QVDisjointSet(const QVGenericImage &image);
00170
00172 QVDisjointSet(const QVDisjointSet &other);
00173
00174
00175
00192 inline uInt find(QPoint p)
00193 {
00194 Q_ASSERT_X(cols > 0, "QVDisjointSet::find", "Number of columns equals 0");
00195 Q_ASSERT_X(rows > 0, "QVDisjointSet::find", "Number of rows equals 0");
00196
00198 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p), "QVDisjointSet::find", "QPoint out of image bounds");
00199 return find(INDEX(p.x(), p.y()));
00200 }
00201
00220 inline uInt find(uInt col, uInt row)
00221 {
00222 Q_ASSERT_X(cols > 0, "QVDisjointSet::find", "Number of columns equals 0");
00223 Q_ASSERT_X(rows > 0, "QVDisjointSet::find", "Number of rows equals 0");
00224 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(col, row)),
00225 "QVDisjointSet::find", "QPoint out of image bounds");
00226 return find(INDEX(col, row));
00227 }
00228
00234 inline uInt find(uInt index)
00235 {
00236 Q_ASSERT_X(index < elements, "QVDisjointSet::find", "Index exceeds number of elements");
00237
00238 if (parent[index] == index)
00239 return index;
00240
00241 if (parent[parent[index]] != parent[index])
00242 parent[index] = find(parent[index]);
00243
00244 return parent[index];
00245 }
00246
00265 inline uInt unify(QPoint p1, QPoint p2)
00266 {
00267 Q_ASSERT_X(cols > 0, "QVDisjointSet::unify", "Number of columns equals 0");
00268 Q_ASSERT_X(rows > 0, "QVDisjointSet::unify", "Number of rows equals 0");
00269 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p1), "QVDisjointSet::unify", "First QPoint out of image bounds");
00270 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p2), "QVDisjointSet::unify", "Second QPoint out of image bounds");
00271
00272 return unify(INDEX(p1.x(),p1.y()),INDEX(p2.x(),p2.y()));
00273 }
00274
00294 inline uInt unify(uInt c1, uInt r1, uInt c2, uInt r2)
00295 {
00296 Q_ASSERT_X(cols > 0, "QVDisjointSet::unify", "Number of columns equals 0");
00297 Q_ASSERT_X(rows > 0, "QVDisjointSet::unify", "Number of rows equals 0");
00298 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(c1, r1)),
00299 "QVDisjointSet::unify", "First QPoint out of image bounds");
00300 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(c2, r2)),
00301 "QVDisjointSet::unify", "Second QPoint out of image bounds");
00302
00303 return unify(INDEX(c1,r1),INDEX(c2,r2));
00304 }
00305
00315 uInt unify(uInt index1, uInt index2);
00316
00321 inline uInt getSetCardinality(const QPoint &p1) { return getSetCardinality(INDEX(p1.x(), p1.y())); }
00322
00328 inline uInt getSetCardinality(uInt col, uInt row) { return getSetCardinality(INDEX(col, row)); }
00329
00334 inline uInt getSetCardinality(uInt index)
00335 {
00336 Q_ASSERT(count[find(index)] > 0);
00337 return count[find(index)];
00338 }
00339
00343 inline uInt numberOfSets() const { return sets; }
00344
00349 inline uInt index(QPoint p) const { return INDEX(p.x(), p.y()); }
00350
00356 inline uInt index(uInt col, uInt row) const { return INDEX(col, row); }
00357
00364 inline bool isRootElement(uInt col, uInt row) const { return isRootElement(INDEX(col, row)); }
00365
00376 inline bool isRootElement(uInt index) const { return parent[index] == index; }
00377
00378 private:
00379 uInt cols, rows, elements, sets;
00380 QVector<uInt> parent, rank, count;
00381
00382
00383 void makeSet();
00384
00385
00386 };
00387 #endif