3 #include <Caribou/config.h>
4 #include <Caribou/Geometry/Element.h>
5 #include <unordered_map>
11 namespace caribou::topology {
14 auto operator()(
const FLOATING_POINT_TYPE& x)
const -> FLOATING_POINT_TYPE {
return std::round(x); }
17 auto operator()(
const FLOATING_POINT_TYPE& x)
const -> FLOATING_POINT_TYPE {
return std::floor(x); }
20 template <
typename Element>
26 using Index = UNSIGNED_INTEGER_TYPE;
27 using GridCoordinates = Eigen::Matrix<INTEGER_TYPE, Dimension, 1>;
28 using WorldCoordinates = Eigen::Matrix<FLOATING_POINT_TYPE, Dimension, 1>;
29 using VecFloat = Eigen::Matrix<FLOATING_POINT_TYPE, Dimension, 1>;
31 HashGrid (
const FLOATING_POINT_TYPE & cell_size) : p_cell_size(cell_size) {}
33 HashGrid (
const FLOATING_POINT_TYPE & cell_size,
const UNSIGNED_INTEGER_TYPE & number_of_elements) : p_cell_size(cell_size) {
34 p_hash_table.reserve(2*number_of_elements);
43 void add(
const Element & e,
const Index &
id) {
44 const auto min = (e.nodes().colwise().minCoeff() * 1/p_cell_size).unaryExpr(CwiseFloor()).eval();
45 const auto max = (e.nodes().colwise().maxCoeff() * 1/p_cell_size).unaryExpr(CwiseFloor()).eval();
47 for (INTEGER_TYPE i = min[0]; i <= max[0]; ++i) {
48 if constexpr (Dimension == 1) {
49 p_hash_table[GridCoordinates {i}].emplace_back(
id);
51 for (INTEGER_TYPE j = min[1]; j <= max[1]; ++j) {
52 if constexpr (Dimension == 2) {
53 p_hash_table[GridCoordinates {i, j}].emplace_back(
id);
55 for (INTEGER_TYPE k = min[2]; k <= max[2]; ++k) {
56 p_hash_table[GridCoordinates {i, j, k}].emplace_back(
id);
70 auto get(
const WorldCoordinates & p)
const -> std::set<Index> {
71 const VecFloat absolute = p / p_cell_size;
72 const VecFloat rounded = absolute.unaryExpr(CwiseRound());
73 const VecFloat distance = absolute - rounded;
75 auto close_to_axis = std::bitset<Dimension>();
77 std::vector<GridCoordinates> cells;
78 cells.reserve((
unsigned) 1<<Dimension);
81 for (UNSIGNED_INTEGER_TYPE axis = 0; axis < Dimension; ++axis) {
82 if (distance[axis]*distance[axis] < EPSILON*EPSILON )
83 close_to_axis[axis] =
true;
86 if (close_to_axis.none()) {
88 cells.emplace_back(absolute.unaryExpr(CwiseFloor()).
template cast<INTEGER_TYPE>());
90 const VecFloat d = VecFloat::Constant(1 / 2.);
92 std::array<std::vector<INTEGER_TYPE>, Dimension> axis_indices;
93 for (
auto & indices : axis_indices) {
94 indices.reserve(Dimension);
97 for (UNSIGNED_INTEGER_TYPE axis = 0; axis < Dimension; ++axis) {
98 if (close_to_axis[axis]) {
99 axis_indices[axis].emplace_back(floor(rounded[axis]-d[axis]));
100 axis_indices[axis].emplace_back(floor(rounded[axis]+d[axis]));
102 axis_indices[axis].emplace_back(floor(absolute[axis]));
106 for (
const INTEGER_TYPE & i : axis_indices[0]) {
107 if constexpr (Dimension == 1) {
108 cells.emplace_back(GridCoordinates{i});
110 for (
const INTEGER_TYPE & j : axis_indices[1]) {
111 if constexpr (Dimension == 2) {
112 cells.emplace_back(GridCoordinates{i, j});
114 for (
const INTEGER_TYPE & k : axis_indices[2]) {
115 cells.emplace_back(GridCoordinates{i, j, k});
123 std::set<Index> elements;
124 for (
const auto & cell_coordinates : cells) {
125 const auto & iter = p_hash_table.find(cell_coordinates);
126 if (iter != p_hash_table.end()) {
127 for (
const auto &element_data : iter->second) {
128 elements.emplace(element_data);
140 auto operator()(
const GridCoordinates & coordinates)
const -> std::size_t
144 INTEGER_TYPE h = 73856093 * coordinates[0] ;
145 if constexpr (Dimension > 1)
146 h ^= 19349663*coordinates[1];
147 if constexpr (Dimension > 2)
148 h ^= 83492791*coordinates[2];
156 auto operator()(
const GridCoordinates &a,
const GridCoordinates &b)
const ->
bool
158 return ((a - b).norm() == 0);
163 FLOATING_POINT_TYPE p_cell_size;
164 std::unordered_map<GridCoordinates, std::vector<Index>, HashFunction, HashEqual> p_hash_table;