mirror of
https://github.com/allemangD/toddcox-visualize.git
synced 2025-11-10 12:02:47 -05:00
Replace ComboIterator with std::set<std::vector<int>> via combinations.hpp
Since the number of generators never exceeds 6, the maximum number of combinations is (6, 3) = 20, so the space optimizations of using an iterator is mute. Doing this way also allows to use set_difference and set_union to deal with collections of subgroups. This is not easily possible otherwise.
This commit is contained in:
44
vis/include/combinations.hpp
Normal file
44
vis/include/combinations.hpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
template<class V>
|
||||||
|
V select(const V &options, const std::vector<bool> &mask, size_t count) {
|
||||||
|
V result;
|
||||||
|
result.reserve(count);
|
||||||
|
|
||||||
|
for (int i = 0; i < mask.size(); ++i) {
|
||||||
|
if (mask[i]) result.push_back(options[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class V>
|
||||||
|
std::set<V> combinations(const V &options, size_t count) {
|
||||||
|
std::set<V> result;
|
||||||
|
|
||||||
|
std::vector<bool> mask(options.size(), false);
|
||||||
|
std::fill(mask.begin(), mask.begin() + count, true);
|
||||||
|
|
||||||
|
do {
|
||||||
|
result.insert(select(options, mask, count));
|
||||||
|
} while (std::next_permutation(mask.begin(), mask.end(), std::greater<>()));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class V>
|
||||||
|
std::set<V> difference(const std::set<V> &a, const std::set<V> &b) {
|
||||||
|
std::set<V> result;
|
||||||
|
|
||||||
|
std::set_difference(
|
||||||
|
a.begin(), a.end(),
|
||||||
|
b.begin(), b.end(),
|
||||||
|
std::inserter(result, result.end())
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <array>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <numeric>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
size_t choose(size_t n, size_t k) {
|
|
||||||
if (k == 0) return 1;
|
|
||||||
return n * choose(n - 1, k - 1) / k;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class ComboIterator {
|
|
||||||
private:
|
|
||||||
const std::vector<T> &options;
|
|
||||||
|
|
||||||
std::vector<bool> bits;
|
|
||||||
std::vector<T> curr;
|
|
||||||
int at;
|
|
||||||
|
|
||||||
void set_curr() {
|
|
||||||
for (int i = 0, j = 0; i < bits.size(); ++i) {
|
|
||||||
if (bits[i]) curr[j++] = options[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
ComboIterator(const std::vector<T> &options, int k, int at = 0)
|
|
||||||
: options(options), bits(options.size()), curr(k), at(at) {
|
|
||||||
std::fill(bits.begin(), bits.begin() + k, true);
|
|
||||||
set_curr();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator==(const ComboIterator<T> &o) const {
|
|
||||||
return at == o.at;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool operator!=(const ComboIterator<T> &o) const {
|
|
||||||
return at != o.at;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto operator*() const {
|
|
||||||
return curr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &operator->() const {
|
|
||||||
return &this;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto operator++(int) {
|
|
||||||
std::prev_permutation(bits.begin(), bits.end());
|
|
||||||
set_curr();
|
|
||||||
++at;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto operator++() &{
|
|
||||||
auto res = *this;
|
|
||||||
(*this)++;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto operator--(int) {
|
|
||||||
std::next_permutation(bits.begin(), bits.end());
|
|
||||||
set_curr();
|
|
||||||
--at;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto operator--() &{
|
|
||||||
auto res = *this;
|
|
||||||
(*this)--;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class Combos {
|
|
||||||
private:
|
|
||||||
const std::vector<T> options;
|
|
||||||
int k;
|
|
||||||
int size;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Combos(const std::vector<T> &options, int k)
|
|
||||||
: options(options), k(k), size(choose(options.size(), k)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ComboIterator<T> begin() const {
|
|
||||||
return ComboIterator<T>(options, k);
|
|
||||||
}
|
|
||||||
|
|
||||||
ComboIterator<T> end() const {
|
|
||||||
return ComboIterator<T>(options, k, size);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -5,7 +5,6 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "combo_iterator.hpp"
|
|
||||||
|
|
||||||
template<unsigned N>
|
template<unsigned N>
|
||||||
using Prims = Eigen::Matrix<unsigned, N, Eigen::Dynamic>;
|
using Prims = Eigen::Matrix<unsigned, N, Eigen::Dynamic>;
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
#include <cgl/pipeline.hpp>
|
#include <cgl/pipeline.hpp>
|
||||||
|
|
||||||
#include <geometry.hpp>
|
#include <geometry.hpp>
|
||||||
#include "mirror.hpp"
|
#include <mirror.hpp>
|
||||||
|
#include <combinations.hpp>
|
||||||
|
|
||||||
struct Matrices {
|
struct Matrices {
|
||||||
mat4 proj = mat4::Identity();
|
mat4 proj = mat4::Identity();
|
||||||
@@ -46,13 +47,13 @@ public:
|
|||||||
cgl::VertexArray vao;
|
cgl::VertexArray vao;
|
||||||
|
|
||||||
explicit Slice(const tc::Group &g) : group(g) {
|
explicit Slice(const tc::Group &g) : group(g) {
|
||||||
auto gens = generators(group);
|
auto ctx = generators(group);
|
||||||
auto combos = Combos<int>(gens, 3);
|
auto all_ctxs = combinations(ctx, N - 1);
|
||||||
std::vector<std::vector<int>> exclude = {{0, 1, 2}};
|
auto selected_ctxs = difference(all_ctxs, {
|
||||||
|
{0, 2, 4},
|
||||||
|
});
|
||||||
|
|
||||||
auto all_sg_gens = combos;
|
auto mesh = Mesh<N>::hull(group, ctx, selected_ctxs);
|
||||||
|
|
||||||
auto mesh = Mesh<N>::hull(g, generators(g), all_sg_gens);
|
|
||||||
ibo.put(mesh);
|
ibo.put(mesh);
|
||||||
|
|
||||||
vao.ipointer(0, ibo, 4, GL_UNSIGNED_INT);
|
vao.ipointer(0, ibo, 4, GL_UNSIGNED_INT);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <geometry.hpp>
|
#include <geometry.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "combo_iterator.hpp"
|
#include <combinations.hpp>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce a list of all generators for the group context. The range [0..group.ngens).
|
* Produce a list of all generators for the group context. The range [0..group.ngens).
|
||||||
@@ -184,7 +184,8 @@ Mesh<N> Mesh<N>::fill(const tc::Group &g, std::vector<int> ctx) {
|
|||||||
if (ctx.size() + 1 != N)
|
if (ctx.size() + 1 != N)
|
||||||
throw std::logic_error("ctx size must be one less than N");
|
throw std::logic_error("ctx size must be one less than N");
|
||||||
|
|
||||||
const auto &combos = Combos(ctx, (int)ctx.size() - 1);
|
// const auto &combos = Combos(ctx, (int)ctx.size() - 1);
|
||||||
|
const auto &combos = combinations(ctx, (int) ctx.size() - 1);
|
||||||
|
|
||||||
std::vector<Mesh<N>> meshes;
|
std::vector<Mesh<N>> meshes;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user