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 <qvcore/qvimage.h>
00029
00030 #define INDEX(Col, Row) (Col*rows + Row)
00031
00146 class QVDisjointSet
00147 {
00148 public:
00155 QVDisjointSet(uInt numElements);
00156
00172 QVDisjointSet(uInt cols, uInt rows);
00173
00187 QVDisjointSet(QVGenericImage &image);
00188
00189 ~QVDisjointSet();
00190
00207 inline const uInt find(QPoint p)
00208 {
00209 Q_ASSERT_X(cols > 0, "QVDisjointSet::find", "Number of columns equals 0");
00210 Q_ASSERT_X(rows > 0, "QVDisjointSet::find", "Number of rows equals 0");
00211
00213 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p), "QVDisjointSet::find", "QPoint out of image bounds");
00214 return find(INDEX(p.x(), p.y()));
00215 }
00216
00235 inline const uInt find(uInt col, uInt row)
00236 {
00237 Q_ASSERT_X(cols > 0, "QVDisjointSet::find", "Number of columns equals 0");
00238 Q_ASSERT_X(rows > 0, "QVDisjointSet::find", "Number of rows equals 0");
00239 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(col, row)),
00240 "QVDisjointSet::find", "QPoint out of image bounds");
00241 return find(INDEX(col, row));
00242 }
00243
00262 inline const uInt unify(QPoint p1, QPoint p2)
00263 {
00264 Q_ASSERT_X(cols > 0, "QVDisjointSet::unify", "Number of columns equals 0");
00265 Q_ASSERT_X(rows > 0, "QVDisjointSet::unify", "Number of rows equals 0");
00266 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p1), "QVDisjointSet::unify", "First QPoint out of image bounds");
00267 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p2), "QVDisjointSet::unify", "Second QPoint out of image bounds");
00268
00269 return unify(INDEX(p1.x(),p1.y()),INDEX(p2.x(),p2.y()));
00270 }
00271
00291 inline const uInt unify(uInt c1, uInt r1, uInt c2, uInt r2)
00292 {
00293 Q_ASSERT_X(cols > 0, "QVDisjointSet::unify", "Number of columns equals 0");
00294 Q_ASSERT_X(rows > 0, "QVDisjointSet::unify", "Number of rows equals 0");
00295 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(c1, r1)),
00296 "QVDisjointSet::unify", "First QPoint out of image bounds");
00297 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(c2, r2)),
00298 "QVDisjointSet::unify", "Second QPoint out of image bounds");
00299
00300 return unify(INDEX(c1,r1),INDEX(c2,r2));
00301 }
00302
00307 inline const uInt getSetCardinality(QPoint p1) { return getSetCardinality(INDEX(p1.x(), p1.y())); }
00308
00314 inline const uInt getSetCardinality(uInt col, uInt row) { return getSetCardinality(INDEX(col, row)); }
00315
00321 inline const uInt find(uInt index)
00322 {
00323 Q_ASSERT_X(index < elements, "QVDisjointSet::find", "Index exceeds number of elements");
00324
00325 if (parent[index] == index)
00326 return index;
00327
00328 if (parent[parent[index]] != parent[index])
00329 parent[index] = find(parent[index]);
00330
00331 return parent[index];
00332 }
00333
00343 const uInt unify(uInt index1, uInt index2);
00344
00349 inline const uInt getSetCardinality(uInt index)
00350 {
00351 Q_ASSERT(count[find(index)] > 0);
00352 return count[find(index)];
00353 }
00354
00358 inline const uInt numberOfSets() const { return sets; }
00359
00364 inline const uInt index(QPoint p) const { return INDEX(p.x(), p.y()); }
00365
00371 inline const uInt index(uInt col, uInt row) const { return INDEX(col, row); }
00372
00379 inline const bool isRootElement(uInt col, uInt row) const { return isRootElement(INDEX(col, row)); }
00380
00391 inline const bool isRootElement(uInt index) const { return parent[index] == index; }
00392
00393 private:
00394 uInt elements, sets, cols, rows;
00395 uInt *parent, *rank, *count;
00396
00397 void makeSet();
00398 void allocData();
00399 void freeData();
00400 };
00401 #endif