// Begin License: // Copyright (C) 2006-2008 Tobias Sargeant (tobias.sargeant@gmail.com). // All rights reserved. // // This file is part of the Carve CSG Library (http://carve-csg.com/) // // This file may be used under the terms of the GNU General Public // License version 2.0 as published by the Free Software Foundation // and appearing in the file LICENSE.GPL2 included in the packaging of // this file. // // This file is provided "AS IS" with NO WARRANTY OF ANY KIND, // INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE. // End: #pragma once #include #include namespace carve { namespace djset { class djset { protected: struct elem { size_t parent, rank; elem(size_t p, size_t r) : parent(p), rank(r) {} elem() {} }; std::vector set; size_t n_sets; public: djset() : set(), n_sets(0) { } djset(size_t N) { n_sets = N; set.reserve(N); for (size_t i = 0; i < N; ++i) { set.push_back(elem(i,0)); } } void init(size_t N) { if (N == set.size()) { for (size_t i = 0; i < N; ++i) { set[i] = elem(i,0); } n_sets = N; } else { djset temp(N); std::swap(set, temp.set); std::swap(n_sets, temp.n_sets); } } size_t count() const { return n_sets; } size_t find_set_head(size_t a) { if (a == set[a].parent) return a; size_t a_head = a; while (set[a_head].parent != a_head) a_head = set[a_head].parent; set[a].parent = a_head; return a_head; } bool same_set(size_t a, size_t b) { return find_set_head(a) == find_set_head(b); } void merge_sets(size_t a, size_t b) { a = find_set_head(a); b = find_set_head(b); if (a != b) { n_sets--; if (set[a].rank < set[b].rank) { set[a].parent = b; } else if (set[b].rank < set[a].rank) { set[b].parent = a; } else { set[a].rank++; set[b].parent = a; } } } void get_index_to_set(std::vector &index_set, std::vector &set_size) { index_set.clear(); index_set.resize(set.size(), n_sets); set_size.clear(); set_size.resize(n_sets, 0); size_t c = 0; for (size_t i = 0; i < set.size(); ++i) { size_t s = find_set_head(i); if (index_set[s] == n_sets) index_set[s] = c++; index_set[i] = index_set[s]; set_size[index_set[s]]++; } } template void collate(in_iter_t in, out_collection_t &out) { std::vector set_id(set.size(), n_sets); out.clear(); out.resize(n_sets); size_t c = 0; for (size_t i = 0; i < set.size(); ++i) { size_t s = find_set_head(i); if (set_id[s] == n_sets) set_id[s] = c++; s = set_id[s]; std::insert_iterator j(out[s], out[s].end()); *j = *in++; } } }; } }