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
00032 namespace qvdta
00033 {
00148 class QVDisjointSet
00149 {
00150 public:
00157 QVDisjointSet(uInt numElements);
00158
00174 QVDisjointSet(uInt cols, uInt rows);
00175
00189 QVDisjointSet(QVGenericImage &image);
00190
00191 ~QVDisjointSet();
00192
00209 inline uInt find(QPoint p)
00210 {
00211 Q_ASSERT_X(cols > 0, "QVDisjointSet::find", "Number of columns equals 0");
00212 Q_ASSERT_X(rows > 0, "QVDisjointSet::find", "Number of rows equals 0");
00213
00215 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p), "QVDisjointSet::find", "QPoint out of image bounds");
00216 return find(INDEX(p.x(), p.y()));
00217 }
00218
00237 inline uInt find(uInt col, uInt row)
00238 {
00239 Q_ASSERT_X(cols > 0, "QVDisjointSet::find", "Number of columns equals 0");
00240 Q_ASSERT_X(rows > 0, "QVDisjointSet::find", "Number of rows equals 0");
00241 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(col, row)),
00242 "QVDisjointSet::find", "QPoint out of image bounds");
00243 return find(INDEX(col, row));
00244 }
00245
00264 inline uInt unify(QPoint p1, QPoint p2)
00265 {
00266 Q_ASSERT_X(cols > 0, "QVDisjointSet::unify", "Number of columns equals 0");
00267 Q_ASSERT_X(rows > 0, "QVDisjointSet::unify", "Number of rows equals 0");
00268 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p1), "QVDisjointSet::unify", "First QPoint out of image bounds");
00269 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p2), "QVDisjointSet::unify", "Second QPoint out of image bounds");
00270
00271 return unify(INDEX(p1.x(),p1.y()),INDEX(p2.x(),p2.y()));
00272 }
00273
00293 inline uInt unify(uInt c1, uInt r1, uInt c2, uInt r2)
00294 {
00295 Q_ASSERT_X(cols > 0, "QVDisjointSet::unify", "Number of columns equals 0");
00296 Q_ASSERT_X(rows > 0, "QVDisjointSet::unify", "Number of rows equals 0");
00297 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(c1, r1)),
00298 "QVDisjointSet::unify", "First QPoint out of image bounds");
00299 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(c2, r2)),
00300 "QVDisjointSet::unify", "Second QPoint out of image bounds");
00301
00302 return unify(INDEX(c1,r1),INDEX(c2,r2));
00303 }
00304
00309 inline uInt getSetCardinality(QPoint p1) { return getSetCardinality(INDEX(p1.x(), p1.y())); }
00310
00316 inline uInt getSetCardinality(uInt col, uInt row) { return getSetCardinality(INDEX(col, row)); }
00317
00323 inline uInt find(uInt index)
00324 {
00325 Q_ASSERT_X(index < elements, "QVDisjointSet::find", "Index exceeds number of elements");
00326
00327 if (parent[index] == index)
00328 return index;
00329
00330 if (parent[parent[index]] != parent[index])
00331 parent[index] = find(parent[index]);
00332
00333 return parent[index];
00334 }
00335
00345 uInt unify(uInt index1, uInt index2);
00346
00347
00352 inline uInt getSetCardinality(uInt index)
00353 {
00354 Q_ASSERT(count[find(index)] > 0);
00355 return count[find(index)];
00356 }
00357
00361 inline uInt numberOfSets() { return sets; }
00362
00367 inline uInt index(QPoint p) { return INDEX(p.x(), p.y()); }
00368
00374 inline uInt index(uInt col, uInt row) { return INDEX(col, row); }
00375
00376 private:
00377 uInt elements, sets, cols, rows;
00378 uInt *parent, *rank, *count;
00379
00380 void makeSet();
00381 void allocData();
00382 void freeData();
00383 };
00384 }
00385 #endif