-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathfill_gaps.h
125 lines (97 loc) · 2.99 KB
/
fill_gaps.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#ifndef FILL_GAPS_H
#define FILL_GAPS_H
#include "storage.h"
#include "edge_detect.h"
typedef bool(abstract_voxel_storage::*voxel_getter_t)(const vec_n<3, size_t>&) const;
typedef void(abstract_voxel_storage::*voxel_setter_t)(const vec_n<3, size_t>&);
namespace {
void specialize_getter_(chunked_voxel_storage<bit_t>* t, voxel_getter_t& getter_, voxel_setter_t& setter_) {
if (!t) {
return;
}
getter_ = static_cast<voxel_getter_t>(&chunked_voxel_storage<bit_t>::Get);
setter_ = static_cast<voxel_setter_t>(&chunked_voxel_storage<bit_t>::Set);
}
void specialize_getter_(abstract_voxel_storage* t, voxel_getter_t& getter_, voxel_setter_t& setter_) {
if (!t) {
return;
}
getter_ = &abstract_voxel_storage::Get;
setter_ = &abstract_voxel_storage::Set;
}
}
class fill_gaps : public post_process {
private:
regular_voxel_storage * storage_;
regular_voxel_storage * output_;
std::array<vec_n<3, size_t>, 2> extents_;
bool(abstract_voxel_storage::*getter_)(const vec_n<3, size_t>&) const;
void(abstract_voxel_storage::*setter_)(const vec_n<3, size_t>&);
bool get_(const vec_n<3, size_t>& pos) {
if ((pos < extents_[0]).any()) {
return false;
}
if ((pos > extents_[1]).any()) {
return false;
}
return (storage_->*getter_)(pos);
}
void init_(regular_voxel_storage* storage) {
storage_ = storage;
output_ = (regular_voxel_storage*)storage_->empty_copy();
extents_ = storage->original_bounds();
getter_ = nullptr;
setter_ = nullptr;
// nah this is likely not going to make a difference
specialize_getter_(storage_, getter_, setter_);
specialize_getter_(dynamic_cast<chunked_voxel_storage<bit_t>*>(storage_), getter_, setter_);
if (dynamic_cast<voxel_region*>(storage_)) {
storage_ = dynamic_cast<voxel_region*>(storage_)->base();
specialize_getter_(dynamic_cast<chunked_voxel_storage<bit_t>*>(storage_), getter_, setter_);
}
}
public:
static const bool UNION_INPUT = true;
regular_voxel_storage* operator()(regular_voxel_storage* storage) {
init_(storage);
size_t i0, i1, j0, j1, k0, k1;
storage->bounds()[0].tie(i0, j0, k0);
storage->bounds()[1].tie(i1, j1, k1);
std::vector<vec_n<3, long>> opposites{
make_vec<long>(1,0,0),
make_vec<long>(0,1,0),
make_vec<long>(0,0,1)
};
vec_n<3, size_t> ijk;
for (long i = i0; i <= (long)i1; ++i) {
progress(static_cast<float>(i - i0) / (i1 - i0));
ijk.get(0) = i;
for (long j = j0; j <= (long)j1; ++j) {
ijk.get(1) = j;
bool inside = false;
for (long k = k0; k <= (long)k1; ++k) {
ijk.get(2) = k;
const vec_n<3, long> ijk = vec_n<3, long>(i, j, k);
if (get_(ijk.as<size_t>())) {
continue;
}
bool opposing_set = false;
for (const auto& opp : opposites) {
if (get_((ijk + opp).as<size_t>()) &&
get_((ijk - opp).as<size_t>()))
{
opposing_set = true;
break;
}
}
if (opposing_set) {
(output_->*setter_)(ijk.as<size_t>());
}
}
}
}
progress(1.);
return output_;
}
};
#endif