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) (Col*rows + Row)
00031
00146 class QVDisjointSet
00147 {
00148 public:
00155 QVDisjointSet(uInt numElements);
00156
00172 QVDisjointSet(uInt cols, uInt rows);
00173
00187 QVDisjointSet(const 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
00249 inline const uInt find(uInt index)
00250 {
00251 Q_ASSERT_X(index < elements, "QVDisjointSet::find", "Index exceeds number of elements");
00252
00253 if (parent[index] == index)
00254 return index;
00255
00256 if (parent[parent[index]] != parent[index])
00257 parent[index] = find(parent[index]);
00258
00259 return parent[index];
00260 }
00261
00280 inline const uInt unify(QPoint p1, QPoint p2)
00281 {
00282 Q_ASSERT_X(cols > 0, "QVDisjointSet::unify", "Number of columns equals 0");
00283 Q_ASSERT_X(rows > 0, "QVDisjointSet::unify", "Number of rows equals 0");
00284 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p1), "QVDisjointSet::unify", "First QPoint out of image bounds");
00285 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p2), "QVDisjointSet::unify", "Second QPoint out of image bounds");
00286
00287 return unify(INDEX(p1.x(),p1.y()),INDEX(p2.x(),p2.y()));
00288 }
00289
00309 inline const uInt unify(uInt c1, uInt r1, uInt c2, uInt r2)
00310 {
00311 Q_ASSERT_X(cols > 0, "QVDisjointSet::unify", "Number of columns equals 0");
00312 Q_ASSERT_X(rows > 0, "QVDisjointSet::unify", "Number of rows equals 0");
00313 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(c1, r1)),
00314 "QVDisjointSet::unify", "First QPoint out of image bounds");
00315 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(c2, r2)),
00316 "QVDisjointSet::unify", "Second QPoint out of image bounds");
00317
00318 return unify(INDEX(c1,r1),INDEX(c2,r2));
00319 }
00320
00330 const uInt unify(uInt index1, uInt index2);
00331
00336 inline const uInt getSetCardinality(const QPoint &p1) { return getSetCardinality(INDEX(p1.x(), p1.y())); }
00337
00343 inline const uInt getSetCardinality(uInt col, uInt row) { return getSetCardinality(INDEX(col, row)); }
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 cols, rows, elements, sets;
00395 uInt *parent, *rank, *count;
00396
00397 void makeSet();
00398 void allocData();
00399 void freeData();
00400 };
00401 #endif