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
00127 class QVDisjointSet
00128 {
00129 public:
00136 QVDisjointSet(uInt numElements);
00137
00153 QVDisjointSet(uInt cols, uInt rows);
00154
00168 QVDisjointSet(const QVGenericImage &image);
00169
00170 ~QVDisjointSet();
00171
00188 inline const uInt find(QPoint p)
00189 {
00190 Q_ASSERT_X(cols > 0, "QVDisjointSet::find", "Number of columns equals 0");
00191 Q_ASSERT_X(rows > 0, "QVDisjointSet::find", "Number of rows equals 0");
00192
00194 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p), "QVDisjointSet::find", "QPoint out of image bounds");
00195 return find(INDEX(p.x(), p.y()));
00196 }
00197
00216 inline const uInt find(uInt col, uInt row)
00217 {
00218 Q_ASSERT_X(cols > 0, "QVDisjointSet::find", "Number of columns equals 0");
00219 Q_ASSERT_X(rows > 0, "QVDisjointSet::find", "Number of rows equals 0");
00220 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(col, row)),
00221 "QVDisjointSet::find", "QPoint out of image bounds");
00222 return find(INDEX(col, row));
00223 }
00224
00230 inline const uInt find(uInt index)
00231 {
00232 Q_ASSERT_X(index < elements, "QVDisjointSet::find", "Index exceeds number of elements");
00233
00234 if (parent[index] == index)
00235 return index;
00236
00237 if (parent[parent[index]] != parent[index])
00238 parent[index] = find(parent[index]);
00239
00240 return parent[index];
00241 }
00242
00261 inline const uInt unify(QPoint p1, QPoint p2)
00262 {
00263 Q_ASSERT_X(cols > 0, "QVDisjointSet::unify", "Number of columns equals 0");
00264 Q_ASSERT_X(rows > 0, "QVDisjointSet::unify", "Number of rows equals 0");
00265 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p1), "QVDisjointSet::unify", "First QPoint out of image bounds");
00266 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p2), "QVDisjointSet::unify", "Second QPoint out of image bounds");
00267
00268 return unify(INDEX(p1.x(),p1.y()),INDEX(p2.x(),p2.y()));
00269 }
00270
00290 inline const uInt unify(uInt c1, uInt r1, uInt c2, uInt r2)
00291 {
00292 Q_ASSERT_X(cols > 0, "QVDisjointSet::unify", "Number of columns equals 0");
00293 Q_ASSERT_X(rows > 0, "QVDisjointSet::unify", "Number of rows equals 0");
00294 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(c1, r1)),
00295 "QVDisjointSet::unify", "First QPoint out of image bounds");
00296 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(c2, r2)),
00297 "QVDisjointSet::unify", "Second QPoint out of image bounds");
00298
00299 return unify(INDEX(c1,r1),INDEX(c2,r2));
00300 }
00301
00311 const uInt unify(uInt index1, uInt index2);
00312
00317 inline const uInt getSetCardinality(const QPoint &p1) { return getSetCardinality(INDEX(p1.x(), p1.y())); }
00318
00324 inline const uInt getSetCardinality(uInt col, uInt row) { return getSetCardinality(INDEX(col, row)); }
00325
00330 inline const uInt getSetCardinality(uInt index)
00331 {
00332 Q_ASSERT(count[find(index)] > 0);
00333 return count[find(index)];
00334 }
00335
00339 inline const uInt numberOfSets() const { return sets; }
00340
00345 inline const uInt index(QPoint p) const { return INDEX(p.x(), p.y()); }
00346
00352 inline const uInt index(uInt col, uInt row) const { return INDEX(col, row); }
00353
00360 inline const bool isRootElement(uInt col, uInt row) const { return isRootElement(INDEX(col, row)); }
00361
00372 inline const bool isRootElement(uInt index) const { return parent[index] == index; }
00373
00374 private:
00375 uInt cols, rows, elements, sets;
00376 uInt *parent, *rank, *count;
00377
00378 void makeSet();
00379 void allocData();
00380 void freeData();
00381 };
00382 #endif