cgv
Loading...
Searching...
No Matches
convex_polyhedron.cxx
1#include "convex_polyhedron.h"
2
3namespace cgv {
4 namespace media {
5 namespace mesh {
6
7
9{
10 /*
11 67
12 45
13 --
14 23
15 01
16 */
17 static unsigned face_vertex_indices[] = {
18 1, 3, 7, 5,
19 0, 4, 6, 2,
20
21 2, 6, 7, 3,
22 1, 5, 4, 0,
23
24 4, 5, 7, 6,
25 0, 2, 3, 1
26 };
27 return face_vertex_indices[4 * fi + ci];
28}
29
31{
32 for (unsigned i = 0; i < F.size() / 2; ++i)
33 std::swap(F[i], F[F.size() - 1 - i]);
34}
35
38{
39 unsigned location_counts[3] = { 0, 0, 0 };
40 for (auto vertex_location : vertex_locations)
41 ++location_counts[to_index(vertex_location)];
42
43 if (location_counts[0] == 0)
44 return VPL_OUTSIDE;
45 if (location_counts[2] == 0)
46 return VPL_INSIDE;
47 return VPL_TOUCH;
48}
49
52{
53 // first check for cases where the complete shell is on one side only
54 unsigned face_nr_outside = 0;
55 unsigned face_nr_inside = 0;
56 unsigned face_nr_split = 0;
57 for (FacePlaneLocation face_location : face_locations) {
58 switch (face_location) {
59 case FPL_OUTSIDE + FPL_TOUCH_NOTHING:
60 case FPL_OUTSIDE + FPL_TOUCH_VERTEX:
61 case FPL_OUTSIDE + FPL_TOUCH_EDGE:
62 ++face_nr_outside;
63 break;
64 case FPL_INSIDE + FPL_TOUCH_NOTHING:
65 case FPL_INSIDE + FPL_TOUCH_VERTEX:
66 case FPL_INSIDE + FPL_TOUCH_EDGE:
67 ++face_nr_inside;
68 break;
69 case FPL_TOUCH_FACE:
70 break;
71 case FPL_SPLIT_TWO_VERTICES:
72 case FPL_SPLIT_VERTEX_EDGE:
73 case FPL_SPLIT_TWO_EDGES:
74 ++face_nr_split;
75 break;
76 default:
77 std::cerr << "found an invalid face location" << std::endl;
78 abort();
79 break;
80 }
81 }
82 // check if no split is necessary
83 if (face_nr_split > 0)
84 return VPL_TOUCH;
85 if (face_nr_inside == 0)
86 return VPL_OUTSIDE;
87 if (face_nr_outside == 0)
88 return VPL_INSIDE;
89 return VPL_TOUCH;
90}
91
92
94std::pair<int, int> convex_polyhedron_base::extract_touching_halfedge(const face_type& F, const std::vector<VertexPlaneLocation>& vertex_locations)
95{
96 std::pair<int, int> halfedge(F.back(), F.front());
97 VertexPlaneLocation last_vertex_location = vertex_locations[halfedge.first];
98 for (auto vi : F) {
99 halfedge.second = vi;
100 VertexPlaneLocation vertex_location = vertex_locations[vi];
101 if (last_vertex_location == VPL_TOUCH && vertex_location == VPL_TOUCH)
102 return halfedge;
103 halfedge.first = vi;
104 last_vertex_location = vertex_location;
105 }
106 std::cerr << "could not find touching halfedge in face" << std::endl;
107 abort();
108}
109
111convex_polyhedron_base::FacePlaneLocation convex_polyhedron_base::get_face_plane_location(const face_type& F, const std::vector<VertexPlaneLocation>& vertex_locations) const
112{
113 // prepare counts
114 unsigned vertex_nr_locations[3] = { 0, 0, 0 };
115 unsigned edge_nr_touches = 0;
116 unsigned edge_nr_splits = 0;
117 unsigned nr_side_transitions = 0;
118
119 // prepare loop over face vertex indices
120 unsigned i = (unsigned)F.size() - 1;
121 VertexPlaneLocation last_vertex_location = vertex_locations[F[i]];
122
123 // determine side (vertex location excluding touch) at end of face vertices
124 VertexPlaneLocation last_vertex_side = last_vertex_location;
125 while (i > 0 && last_vertex_side == VPL_TOUCH)
126 last_vertex_side = vertex_locations[F[--i]];
127 // if all vertices touch, return face_touch-event
128 if (last_vertex_side == VPL_TOUCH)
129 return FPL_TOUCH_FACE;
130
131 // loop face vertex indices and update counts
132 for (i = 0; i < F.size(); ++i) {
133 int vi = F[i];
134 VertexPlaneLocation vertex_location = vertex_locations[vi];
135
136 ++vertex_nr_locations[to_index(vertex_location)];
137
138 if (vertex_location == VPL_TOUCH) {
139 if (last_vertex_location == VPL_TOUCH)
140 ++edge_nr_touches;
141 }
142 else {
143 if (last_vertex_location != VPL_TOUCH && vertex_location != last_vertex_location)
144 ++edge_nr_splits;
145 if (vertex_location != last_vertex_side)
146 ++nr_side_transitions;
147 last_vertex_side = vertex_location;
148 }
149 last_vertex_location = vertex_location;
150 }
151
152 // analyze counts to locate face
153 FacePlaneLocation face_location = FPL_UNCONSIDERED_CASE;
154
155 // handle side and touch cases
156 if (vertex_nr_locations[to_index(VPL_INSIDE)] == 0 || vertex_nr_locations[to_index(VPL_OUTSIDE)] == 0) {
157 face_location = vertex_nr_locations[to_index(VPL_INSIDE)] > 0 ? FPL_INSIDE : FPL_OUTSIDE;
158 if (vertex_nr_locations[to_index(VPL_TOUCH)] == 1)
159 (int&)face_location += (int)FPL_TOUCH_VERTEX;
160 else if (vertex_nr_locations[to_index(VPL_TOUCH)] == 2) {
161 if (edge_nr_touches == 1)
162 (int&)face_location += (int)FPL_TOUCH_EDGE;
163 else {
164 if (edge_nr_touches != 0) {
165 std::cerr << "unconsidered case (v#+|-=0, v#0=2, e#0>1)" << std::endl;
166 abort();
167 }
168 face_location = FPL_TWO_NON_ADJACENT_VERTICES_TOUCH;
169 }
170 }
171 else if(vertex_nr_locations[to_index(VPL_TOUCH)] != 0)
172 face_location = FPL_UNCONSIDERED_CASE;
173 }
174
175 // handle valid and invalid single split cases
176 if (nr_side_transitions == 2) {
177 if (vertex_nr_locations[to_index(VPL_TOUCH)] == 2 && edge_nr_splits == 0)
178 face_location = FPL_SPLIT_TWO_VERTICES;
179 else if (vertex_nr_locations[to_index(VPL_TOUCH)] == 1 && edge_nr_splits == 1)
180 face_location = FPL_SPLIT_VERTEX_EDGE;
181 else if (vertex_nr_locations[to_index(VPL_TOUCH)] == 0 && edge_nr_splits == 2)
182 face_location = FPL_SPLIT_TWO_EDGES;
183 else if (vertex_nr_locations[to_index(VPL_TOUCH)] + edge_nr_splits > 2)
184 face_location = FPL_TOUCH_AND_SPLIT;
185 else
186 face_location = FPL_UNCONSIDERED_CASE;
187 }
188
189 // handle remaining failure cases
190 if (face_location == FPL_UNCONSIDERED_CASE) {
191 if (vertex_nr_locations[to_index(VPL_TOUCH)] > 2)
192 face_location = FPL_INCOMLETE_TOUCH_FACE;
193 else if (nr_side_transitions % 2 == 1)
194 face_location = FPL_ODD_TRANSITION_NUMBER;
195 else if (nr_side_transitions > 2)
196 face_location = FPL_MULTI_SPLIT;
197 else
198 face_location = FPL_UNCONSIDERED_CASE;
199 }
200
201 return face_location;
202}
203
204
207{
208 // compute vertex indices used in faces of shells
209 std::vector<bool> vertex_index_used(get_nr_vertices(), false);
210 for (const auto& S : shells)
211 for (const auto& F : S)
212 for (int vi : F)
213 vertex_index_used[vi] = true;
214
215 // compute new vertex indices
216 std::vector<int> new_vertex_indices;
217 new_vertex_indices.resize(get_nr_vertices());
218 int new_vertex_index = 0;
219 unsigned vi;
220 for (vi = 0; vi < get_nr_vertices(); ++vi) {
221 new_vertex_indices[vi] = new_vertex_index;
222 if (vertex_index_used[vi])
223 ++new_vertex_index;
224 }
225
226 // remove unused vertices
227 for (vi = (unsigned)get_nr_vertices(); vi > 0;)
228 if (!vertex_index_used[--vi])
229 del_vertex(vi);
230
231 // update vertex indices in shell faces
232 for (auto& S : shells)
233 for (auto& F : S)
234 for (int& vi : F)
235 vi = new_vertex_indices[vi];
236}
237
238/*
239void test_convex_polyhedron()
240{
241 convex_polyhedron<float,3> sdmt;
242 sdmt.construct_box(convex_polyhedron<float>::box_type(convex_polyhedron<float>::point_type(-1, -1, -1), convex_polyhedron<float>::point_type(1, 1, 1)));
243 sdmt.split_at_plane(0, convex_polyhedron<float>::plane_type(1, 0, 0, 0));
244 sdmt.clip_to_outside_of_plane(0, convex_polyhedron<double>::plane_type(1, 0, 0, 0));
245
246 convex_polyhedron<double,3> sdmT;
247 sdmT.construct_box(convex_polyhedron<double>::box_type(convex_polyhedron<double>::point_type(-1, -1, -1), convex_polyhedron<double>::point_type(1, 1, 1)));
248 sdmT.split_at_plane(0, convex_polyhedron<double>::plane_type(1, 0, 0, 0));
249 sdmT.clip_to_inside_of_plane(0, convex_polyhedron<double>::plane_type(1, 0, 0, 0));
250}
251*/
252 }
253 }
254}
void remove_redundant_vertices()
remove redundant vertices from mesh
std::vector< shell_type > shells
vector of shells
VertexPlaneLocation
enumeration of different vertex locations with respect to plane
static VertexPlaneLocation shell_location_side(const std::vector< FacePlaneLocation > &face_locations)
check whether all faces of a shell lay on one side of the plane or touch it, but not on the other sid...
virtual void del_vertex(int vi)=0
virtual method to be implemented in derived class
static int to_index(VertexPlaneLocation vertex_location)
convert VertexPlaneLocation to an index in the range {0 .. 2}
std::vector< int > face_type
a face is an oriented list of vertex indices
static int box_get_face_vertex_index(int fi, int ci)
function implementing the connectivity of an axis aligned box
static VertexPlaneLocation vertex_location_side(const std::vector< VertexPlaneLocation > &vertex_locations)
check whether all vertices lay on one side of the plane or on it, but not on the other; return side o...
virtual size_t get_nr_vertices() const =0
return current number of vertices
FacePlaneLocation
enumeration of 11 valid and 5 invalid cases that a face can be located with respect to a plane after ...
static void change_orientation(face_type &face)
revert the orientation of a face in place, where the face is given by a list of vertex indices
static std::pair< int, int > extract_touching_halfedge(const face_type &face, const std::vector< VertexPlaneLocation > &vertex_locations)
given a face as a list of vertex indices and a vector of vertex locations, find a halfedge that touch...
FacePlaneLocation get_face_plane_location(const face_type &face, const std::vector< VertexPlaneLocation > &vertex_locations) const
given a face as a list of vertex indices and a vector of vertex locations, determine the face locatio...
the cgv namespace
Definition print.h:11