-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbox.cxx
111 lines (108 loc) · 2.6 KB
/
box.cxx
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
#include "implicit_primitive.h"
template <typename T>
struct box : public implicit_primitive<T>
{
/// main templated superclass which we want to inherit stuff from
typedef implicit_primitive<T> base;
using typename base::vec_type;
using typename base::pnt_type;
using base::gui_color;
using base::evaluate_gradient;
using base::add_member_control;
bool use_euclidean_distance;
box() : use_euclidean_distance(true) {}
std::string get_type_name() const { return "box"; }
static int abs_max_idx(const pnt_type& p)
{
if (fabs(p(0)) > fabs(p(1))) {
if (fabs(p(0)) > fabs(p(2)))
return 0;
else
return 2;
}
else {
if (fabs(p(1)) > fabs(p(2)))
return 1;
else
return 2;
}
}
void on_set(void* member_ptr) { base::update_scene(); }
/// evaluate the implicit function itself, this must be overloaded
T evaluate(const pnt_type& p) const {
if (use_euclidean_distance) {
int i;
T distance = 0;
for (i = 0; i < 3; ++i) {
if (p(i) < -1)
distance += sqr(p(i) + 1);
else if (p(i) > 1)
distance += sqr(p(i) - 1);
}
// if we are outside of box, we are done
if (distance > 0)
return sqrt(distance);
// otherwise compute minimum distance to box faces
distance = 2;
for (i = 0; i < 3; ++i) {
if (p(i) + 1 < distance)
distance = p(i) + 1;
if (1 - p(i) < distance)
distance = 1 - p(i);
}
// and return negative distance as we are in the interior of the box
return -distance;
}
else {
return abs(p(abs_max_idx(p))) - 1;
}
}
vec_type evaluate_gradient(const pnt_type& p) const {
if (use_euclidean_distance) {
int i;
vec_type g(0, 0, 0);
T distance = 0;
for (i = 0; i < 3; ++i) {
if (p(i) < -1) {
distance += sqr(p(i) + 1);
g(i) = p(i);
}
else if (p(i) > 1) {
distance += sqr(p(i) - 1);
g(i) = p(i) - 1;
}
}
// if we are outside of box, we are done
if (distance > 0)
return T(1)/distance * g;
// otherwise compute minimum distance to box faces
distance = 1;
for (i = 0; i < 3; ++i) {
if (p(i) + 1 < distance) {
distance = p(i) + 1;
g = T(0);
g(i) = -1;
}
if (1 - p(i) < distance) {
distance = 1 - p(i);
g = T(0);
g(i) = 1;
}
}
// and return negative distance as we are in the interior of the box
return g;
}
else {
vec_type g(0, 0, 0);
int i = abs_max_idx(p);
g(i) = p(i) > 0 ? 1 : -1;
return g;
}
}
void create_gui()
{
base::create_gui();
add_member_control(this, "use_euclidean_distance", use_euclidean_distance, "check");
}
};
scene_factory_registration<box<double> >sfr_box("box;B");