src/qvmath/qvdisjointset.h

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007, 2008. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
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