Handles.hpp
Go to the documentation of this file.
1 
28 /*
29  * Handles.hpp
30  *
31  * @date 15.06.2017
32  * @author Lukas Kalbertodt <lukas.kalbertodt@gmail.com>
33  */
34 
35 #ifndef LVR2_GEOMETRY_HANDLES_H_
36 #define LVR2_GEOMETRY_HANDLES_H_
37 
38 #include <cstdint>
39 #include <functional>
40 
41 #include "lvr2/util/BaseHandle.hpp"
42 
43 namespace lvr2
44 {
45 
96 using Index = uint32_t;
97 
98 // Note on strongly typed handles:
99 //
100 // You might ask: Why do we need that many classes for handles? Wouldn't one
101 // be enough? Or you go even further: if every handle is just a simple integer,
102 // why not store the integer directly. Well, it all comes down to "strong
103 // typing".
104 //
105 // Type systems are the main way for compilers to notice that a program is
106 // faulty. While compiler errors are just annoying in the first few years of
107 // learning how to program, they become very useful later on. When writing
108 // software, humans will make mistakes -- that's just a fact. The question is
109 // WHEN we want to notice those mistakes. There are a few possibilities here:
110 //
111 // - while compiling
112 // - while executing unit tests
113 // - in production
114 //
115 // No one wants to notice bugs when already running software in production. Thus
116 // we want to notice our mistakes earlier. Since this whole library clearly
117 // doesn't care about unit tests, mistakes can only be noticed either at
118 // compile time or when the developer executes the program.
119 //
120 // Well, now the fun parts. When you use a language with a sufficiently
121 // powerful type system (as C++) and if you are correctly using this type
122 // system, you can avoid many huge classes of bugs! The compiler will tell you
123 // right away, when you made a mistake.
124 //
125 // So with these strongly typed handles, you cannot falsely assign an EdgeHandle
126 // to a FaceHandle -- it will result in a compiler error. If you were using
127 // simple integers, the compiler wouldn't notice and you would have to track
128 // down the bug manually. Not so great.
129 //
130 // Apart from that: it makes reading code so much easier, as you know exactly
131 // what a specific parameter is for.
132 
134 class EdgeHandle : public BaseHandle<Index>
135 {
137 };
138 
140 class FaceHandle : public BaseHandle<Index>
141 {
143 };
144 
146 class VertexHandle : public BaseHandle<Index>
147 {
149 };
150 
152 class ClusterHandle : public BaseHandle<Index>
153 {
155 };
156 
158 class TextureHandle : public BaseHandle<Index>
159 {
161 };
162 
164 class OptionalEdgeHandle : public BaseOptionalHandle<Index, EdgeHandle>
165 {
167 };
168 
170 class OptionalFaceHandle : public BaseOptionalHandle<Index, FaceHandle>
171 {
173 };
174 
176 class OptionalVertexHandle : public BaseOptionalHandle<Index, VertexHandle>
177 {
179 };
180 
182 class OptionalClusterHandle : public BaseOptionalHandle<Index, ClusterHandle>
183 {
185 };
186 
187 inline std::ostream& operator<<(std::ostream& os, const EdgeHandle& h)
188 {
189  os << "E" << h.idx();
190  return os;
191 }
192 
193 inline std::ostream& operator<<(std::ostream& os, const FaceHandle& h)
194 {
195  os << "F" << h.idx();
196  return os;
197 }
198 
199 inline std::ostream& operator<<(std::ostream& os, const VertexHandle& h)
200 {
201  os << "V" << h.idx();
202  return os;
203 }
204 
205 inline std::ostream& operator<<(std::ostream& os, const ClusterHandle& h)
206 {
207  os << "C" << h.idx();
208  return os;
209 }
210 
211 inline std::ostream& operator<<(std::ostream& os, const OptionalEdgeHandle& h)
212 {
213  if (h)
214  {
215  os << "E" << h.unwrap().idx();
216  }
217  else
218  {
219  os << "E⊥";
220  }
221  return os;
222 }
223 
224 inline std::ostream& operator<<(std::ostream& os, const OptionalFaceHandle& h)
225 {
226  if (h)
227  {
228  os << "F" << h.unwrap().idx();
229  }
230  else
231  {
232  os << "F⊥";
233  }
234  return os;
235 }
236 
237 inline std::ostream& operator<<(std::ostream& os, const OptionalVertexHandle& h)
238 {
239  if (h)
240  {
241  os << "V" << h.unwrap().idx();
242  }
243  else
244  {
245  os << "V⊥";
246  }
247  return os;
248 }
249 
250 inline std::ostream& operator<<(std::ostream& os, const OptionalClusterHandle& h)
251 {
252  if (h)
253  {
254  os << "C" << h.unwrap().idx();
255  }
256  else
257  {
258  os << "C⊥";
259  }
260  return os;
261 }
262 
263 } // namespace lvr2
264 
265 namespace std
266 {
267 
268 template<>
269 struct hash<lvr2::EdgeHandle> {
270  size_t operator()(const lvr2::EdgeHandle& h) const
271  {
272  return std::hash<lvr2::Index>()(h.idx());
273  }
274 };
275 
276 template<>
277 struct hash<lvr2::FaceHandle> {
278  size_t operator()(const lvr2::FaceHandle& h) const
279  {
280  return std::hash<lvr2::Index>()(h.idx());
281  }
282 };
283 
284 template<>
285 struct hash<lvr2::VertexHandle> {
286  size_t operator()(const lvr2::VertexHandle& h) const
287  {
288  return std::hash<lvr2::Index>()(h.idx());
289  }
290 };
291 
292 template<>
293 struct less<lvr2::VertexHandle> {
294  bool operator()(const lvr2::VertexHandle& l, const lvr2::VertexHandle& r) const
295  {
296  return std::less<lvr2::Index>()(l.idx(), r.idx());
297  }
298 };
299 
300 template<>
301 struct hash<lvr2::ClusterHandle> {
302  size_t operator()(const lvr2::ClusterHandle& h) const
303  {
304  return std::hash<lvr2::Index>()(h.idx());
305  }
306 };
307 
308 template<>
309 struct hash<lvr2::TextureHandle> {
310  size_t operator()(const lvr2::TextureHandle& h) const
311  {
312  return std::hash<lvr2::Index>()(h.idx());
313  }
314 };
315 
316 } // namespace std
317 
318 #endif /* LVR2_GEOMETRY_HANDLES_H_ */
NonOptionalT unwrap() const
Extracts the handle. If this doesn&#39;t hold a handle (is "None"), this method panics.
std::ostream & operator<<(std::ostream &os, const BaseVector< T > &v)
Definition: BaseVector.hpp:227
Interface for all kinds of handles. Handles are basically a key to refer to something.
Definition: BaseHandle.hpp:54
Handle to access vertices of the mesh.
Definition: Handles.hpp:146
size_t operator()(const lvr2::ClusterHandle &h) const
Definition: Handles.hpp:302
size_t operator()(const lvr2::VertexHandle &h) const
Definition: Handles.hpp:286
Handle to access edges of the mesh.
Definition: Handles.hpp:134
uint32_t Index
Datatype used as index for each vertex, face and edge.
Definition: Handles.hpp:96
size_t operator()(const lvr2::TextureHandle &h) const
Definition: Handles.hpp:310
size_t operator()(const lvr2::FaceHandle &h) const
Definition: Handles.hpp:278
Semantically equivalent to boost::optional<VertexHandle>
Definition: Handles.hpp:176
Semantically equivalent to boost::optional<ClusterHandle>
Definition: Handles.hpp:182
Handle to access textures of the mesh.
Definition: Handles.hpp:158
Handle to access Cluster of the ClusterBiMap.
Definition: Handles.hpp:152
Semantically equivalent to boost::optional<FaceHandle>
Definition: Handles.hpp:170
bool operator()(const lvr2::VertexHandle &l, const lvr2::VertexHandle &r) const
Definition: Handles.hpp:294
IdxT idx() const
Base class for optional handles (handles that can be "null" or "None").
Definition: BaseHandle.hpp:79
size_t operator()(const lvr2::EdgeHandle &h) const
Definition: Handles.hpp:270
Handle to access faces of the mesh.
Definition: Handles.hpp:140
Semantically equivalent to boost::optional<EdgeHandle>
Definition: Handles.hpp:164


lvr2
Author(s): Thomas Wiemann , Sebastian Pütz , Alexander Mock , Lars Kiesow , Lukas Kalbertodt , Tristan Igelbrink , Johan M. von Behren , Dominik Feldschnieders , Alexander Löhr
autogenerated on Mon Feb 28 2022 22:46:06