Virtual Testbed
Ship dynamics simulator for extreme conditions
polyhedron.hh
1 #ifndef VTESTBED_GEOMETRY_POLYHEDRON_HH
2 #define VTESTBED_GEOMETRY_POLYHEDRON_HH
3 
4 #include <iosfwd>
5 #include <vector>
6 
7 #include <vtestbed/base/bstream.hh>
8 #include <vtestbed/geometry/face.hh>
9 #include <vtestbed/geometry/rectangle.hh>
10 #include <vtestbed/geometry/triangle.hh>
11 #include <vtestbed/geometry/types.hh>
12 
13 namespace vtb {
14 
16  namespace geometry {
17 
18  template <class T>
19  class Bounds {
20 
21  private:
22  T _min{}, _max{};
23 
24  public:
25  Bounds() = default;
26  inline Bounds(T a, T b): _min(a), _max(b) {}
27  inline T min() const { return this->_min; }
28  inline T max() const { return this->_max; }
29 
30  };
31 
42  template <class T,int N=3>
43  class Polyhedron {
44 
45  public:
46  static constexpr const int dimensions = N;
47  using scalar_type = T;
48  using vertex_type = Vertex<T,N>;
49  using face_type = Face<3>;
52  using size_type = size_t;
53  using index_type = typename face_type::value_type;
54  using box_type = Rectangle<T,N>;
57  using bsp_tree = BSP_tree<T,N>;
58 
59  private:
62  using blitz_vertex_array = blitz::Array<vertex_type,1>;
63  using blitz_face_array = blitz::Array<face_type,1>;
64 
65  private:
66  vertex_array _vertices;
67  vertex_array _vertex_normals;
68  face_array _faces;
69  vertex_array _face_normals;
70 
71  public:
72 
73  Polyhedron() = default;
74  ~Polyhedron() = default;
75  Polyhedron(const Polyhedron&) = default;
76  Polyhedron& operator=(const Polyhedron&) = default;
77  Polyhedron(Polyhedron&&) = default;
78  Polyhedron& operator=(Polyhedron&&) = default;
79 
80  inline explicit
81  Polyhedron(const vertex_array& vertices, const face_array& faces):
82  _vertices(vertices), _faces(faces) {}
83 
84  inline explicit
85  Polyhedron(
86  const vertex_array& vertices,
87  const vertex_array& vertex_normals,
88  const face_array& faces
89  ):
90  _vertices(vertices),
91  _vertex_normals(vertex_normals),
92  _faces(faces) {}
93 
94  explicit
95  Polyhedron(
96  const blitz_vertex_array& vertices,
97  const blitz_face_array& faces
98  );
99 
100  explicit
101  Polyhedron(const triangle_array& triangles);
102 
103  explicit
104  Polyhedron(const bsp_tree& tree);
105 
106  inline const vertex_array&
107  vertices() const noexcept {
108  return this->_vertices;
109  }
110 
111  inline const vertex_array&
112  vertex_normals() const noexcept {
113  return this->_vertex_normals;
114  }
115 
116  inline const vertex_array&
117  face_normals() const noexcept {
118  return this->_face_normals;
119  }
120 
121  inline const face_array&
122  faces() const noexcept {
123  return this->_faces;
124  }
125 
126  void clear();
127  void clear_normals();
128  void shrink_to_fit();
129  scalar_type average_face_area() const;
130  scalar_type signed_volume() const;
131  scalar_type signed_volume_below(int dimension, scalar_type level) const;
132  vertex_type centre() const;
133  vertex_type centroid() const;
134  vertex_type centroid_below(int dimension, scalar_type level) const;
135  box_type bounding_box() const;
136  Bounds<T> bounds(int dimension) const;
137  void swap(Polyhedron& rhs);
138 
139  inline scalar_type
140  signed_volume_below_centroid(int dimension) const {
141  return this->signed_volume_below(dimension,
142  this->centroid()(dimension));
143  }
144 
153  void normalise();
154 
160  void normalise_faces();
161 
180  void reorder();
181 
189  void unique();
190 
198  void merge(const Polyhedron& rhs);
199 
200  inline Polyhedron&
201  operator+=(const Polyhedron& rhs) {
202  this->merge(rhs);
203  return *this;
204  }
205 
206  void cut_duplicate_faces();
207  void remove_face(const vertex_type& vertex);
208  void remove_face(index_type vertex);
209 
210  inline bool
211  empty() const {
212  return this->vertices().empty() &&
213  this->vertex_normals().empty() &&
214  this->faces().empty() &&
215  this->face_normals().empty();
216  }
217 
218  triangle_array triangles() const;
219  blitz_vertex_array blitz_vertices() const;
220  blitz_vertex_array blitz_vertex_normals() const;
221  blitz_face_array blitz_faces() const;
222 
224  void move_to_centre_of_mass();
225 
230  void move_to_centre_of_mass(T draught);
231 
234 
235  void move(const vertex_type& delta);
236 
238  void scale(const vertex_type& ratio);
239 
242  void wall(scalar_type thickness);
243 
245  void flip(int dimension);
246 
248  void mirror(int dimension);
249 
261  void rotate(int dimension, int degrees);
262 
271  return mass_moments_below(0, std::numeric_limits<T>::max());
272  }
273  Mass_moments<T,N> mass_moments_below(int dimension, scalar_type level) const;
274 
275  void gnuplot(std::ostream& out) const;
276  void object(std::ostream& out) const;
277 
278  private:
279 
280  index_array_2d
281  vertex_faces() const;
282 
285  index_array_2d
286  component_faces(const index_array_2d& vf) const;
287 
289  index_type
290  reference_face_index(
291  const index_array& indices,
292  const vertex_type& origin
293  ) const;
294 
296  void reorder(index_type reference_face_index, const vertex_type& origin);
297  void remove_duplicate_vertices();
298  void remove_duplicate_faces();
299 
300  template <class X, int M>
301  friend vtb::core::bstream&
302  operator>>(vtb::core::bstream& in, Polyhedron<X,M>& rhs);
303 
304  };
305 
306  template <class T, int N>
307  inline void
308  swap(Polyhedron<T,N>& lhs, Polyhedron<T,N>& rhs) {
309  lhs.swap(rhs);
310  }
311 
312  template <class T, int N>
313  inline Vertex<T,N>
314  centroid(const Polyhedron<T,N>& geometry) {
315  return geometry.centroid();
316  }
317 
318  template <class T, int N>
319  inline T
320  signed_volume(const Polyhedron<T,N>& geometry) {
321  return geometry.signed_volume();
322  }
323 
324  template <class T, int N>
325  inline T
326  volume(const Polyhedron<T,N>& geometry) {
327  return std::abs(signed_volume(geometry));
328  }
329 
330  template <class T, int N>
331  inline Polyhedron<T,N>
332  operator+(const Polyhedron<T,N>& lhs, const Polyhedron<T,N>& rhs) {
333  return Polyhedron<T,N>(lhs) += rhs;
334  }
335 
336  template <class T, int N>
338  operator<<(vtb::core::bstream& out, const Polyhedron<T,N>& rhs);
339 
340  template <class T, int N>
342  operator>>(vtb::core::bstream& in, Polyhedron<T,N>& rhs);
343 
344  template <class T,int N>
345  T
346  winding_number(const Polyhedron<T,N>& geometry, const Vertex<T,N>& origin);
347 
355  template <class T, int N>
356  Inertia_tensor<T,N>
357  inertia_tensor(const Polyhedron<T,N>& body);
358 
359  }
360 
361 }
362 
363 template <class T>
364 struct vtb::base::has_begin_end<std::vector<T>>: public std::true_type {};
365 template <class T>
366 struct vtb::base::has_reserve_emplace_back<std::vector<T>>: public std::true_type {};
367 
368 #endif // vim:filetype=cpp
void flip(int dimension)
Flip the geometry over specified axis.
Mass_moments< T, N > mass_moments() const
Calculate volume, centre of mass and inertia tensor.
Definition: polyhedron.hh:270
void reorder()
Fix face indices winding order.
Inertia_tensor< T, N > inertia_tensor(const Polyhedron< T, N > &body)
Calculate inertia tensor (matrix) of a body as a sum of inertia tensors for tetrahedrons.
void normalise_faces()
Compute face normals only.
void move_to_centre_of_bounding_box()
Move origin to centre of bounding box.
void unique()
Remove duplicate vertices and faces.
void scale(const vertex_type &ratio)
Scale the geometry by specified ratio over each dimension.
void move_to_centre_of_mass()
Move origin to centre of mass.
Main namespace.
Definition: convert.hh:9
Three-dimensional polyhedron.
Definition: polyhedron.hh:43
void normalise()
Compute face and vertex normals in one loop.
void wall(scalar_type thickness)
Shrink or extend the geometry by thickness in the direction of centroid.
void mirror(int dimension)
Extend the geometry by mirroring it over the specified axis.
void merge(const Polyhedron &rhs)
Add all vertices, faces and normals from rhs.
void rotate(int dimension, int degrees)
Rotate the geometry by angle which is multiple of 90 degrees.