Uses rules to generalize "same color"
This commit is contained in:
parent
5077d7e966
commit
65a7153572
2 changed files with 15 additions and 14 deletions
|
@ -16,42 +16,39 @@ auto make_empty(Field field, Cluster const & c){
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template <typename Field>
|
template <typename Field, typename Rules>
|
||||||
auto same_group(Field const & field, typename Field::Position const & p, typename Field::Position const & q){
|
void cluster_expand(Field const & field, Rules const & rules, typename Field::Position const & p, boost::container::flat_set<typename Field::Position>& ret){
|
||||||
return field.get(p) == field.get(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Field>
|
|
||||||
void cluster_expand(Field const & field, typename Field::Position const & p, boost::container::flat_set<typename Field::Position>& ret){
|
|
||||||
for(auto&& q : field.neighbors(p)){
|
for(auto&& q : field.neighbors(p)){
|
||||||
if(!same_group(field, p, q)) continue;
|
if(!rules.same_cluster(field.get(p), field.get(q))) continue;
|
||||||
|
|
||||||
if(ret.insert(q).second){
|
if(ret.insert(q).second){
|
||||||
cluster_expand(field, q, ret);
|
cluster_expand(field, rules, q, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Field>
|
template <typename Field, typename Rules>
|
||||||
auto cluster_at(Field const & field, typename Field::Position const & p){
|
auto cluster_at(Field const & field, Rules const & rules, typename Field::Position const & p){
|
||||||
boost::container::flat_set<typename Field::Position> ret;
|
boost::container::flat_set<typename Field::Position> ret;
|
||||||
ret.reserve(10); // speed improvement of 20%
|
ret.reserve(10); // speed improvement of 20%
|
||||||
ret.insert(p);
|
ret.insert(p);
|
||||||
detail::cluster_expand(field, p, ret);
|
detail::cluster_expand(field, rules, p, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Grid, typename Rules>
|
template <typename Grid, typename Rules>
|
||||||
auto all_clusters(Grid const & grid, Rules const & rules){
|
auto all_clusters(Grid const & grid, Rules const & rules){
|
||||||
std::vector<decltype(cluster_at(grid, std::declval<typename Grid::Position>()))> ret;
|
std::vector<decltype(cluster_at(grid, rules, std::declval<typename Grid::Position>()))> ret;
|
||||||
ret.reserve(10);
|
ret.reserve(10);
|
||||||
|
|
||||||
auto partition = make_empty(grid, grid.all_positions());
|
auto partition = make_empty(grid, grid.all_positions());
|
||||||
auto current_p = 1;
|
auto current_p = 1;
|
||||||
for(auto&& p : partition.all_positions()){
|
for(auto&& p : partition.all_positions()){
|
||||||
|
// ignore if it already belongs to a cluster or is empty
|
||||||
if(!partition.empty(p) || grid.empty(p)) continue;
|
if(!partition.empty(p) || grid.empty(p)) continue;
|
||||||
|
|
||||||
auto cluster = cluster_at(grid, p);
|
auto cluster = cluster_at(grid, rules, p);
|
||||||
for(auto&& q : cluster){
|
for(auto&& q : cluster){
|
||||||
partition.get(q) = current_p;
|
partition.get(q) = current_p;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,10 @@ struct BasicRules {
|
||||||
return min_size;
|
return min_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto same_cluster(int x, int y) const {
|
||||||
|
return x == y;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int min_size;
|
unsigned int min_size;
|
||||||
};
|
};
|
||||||
|
|
Reference in a new issue