Polytope.h
Go to the documentation of this file.
1 /*
2  This file is part of the Ristra Wonton project.
3  Please see the license file at the root of this repository, or at:
4  https://github.com/laristra/wonton/blob/master/LICENSE
5 */
6 
7 #ifndef WONTON_POLYTOPE_H_
8 #define WONTON_POLYTOPE_H_
9 
10 #include <vector>
11 #include <array>
12 #include <algorithm>
13 #include <numeric>
14 
15 #include "wonton/support/wonton.h"
16 #include "wonton/support/Point.h"
17 
18 namespace Wonton {
19 
20 template <int D>
21 class Polytope {
22 public:
28  explicit Polytope(const std::vector< Point<2> >& vertex_points) {
29  int nfaces = static_cast<int>(vertex_points.size());
30  assert(nfaces > 2);
31 
32  vertex_points_ = vertex_points;
33  face_vertices_.resize(nfaces);
34  for (int iface = 0; iface < nfaces; iface++)
35  face_vertices_[iface] = { iface, (iface + 1)%nfaces };
36  }
37 
45  Polytope(const std::vector< Point<3> >& vertex_points,
46  const std::vector< std::vector<int> >& face_vertices) {
47  assert(vertex_points.size() > 3);
48  assert(face_vertices.size() > 3);
49 
50  vertex_points_ = vertex_points;
51  face_vertices_ = face_vertices;
52  }
53 
55  ~Polytope() = default;
56 
61  const std::vector< Point<D> >& points() const { return vertex_points_; }
62 
70  const std::vector<int>& face_vertices(int const face_id) const {
71  assert((face_id >= 0) && (unsigned(face_id) < face_vertices_.size()));
72  return face_vertices_[face_id];
73  }
74 
82  std::vector< Point<D> > face_points(int const face_id) const {
83  assert((face_id >= 0) && (unsigned(face_id) < face_vertices_.size()));
84 
85  int nvrts = static_cast<int>(face_vertices_[face_id].size());
86  std::vector< Point<D> > fpoints;
87  fpoints.reserve(nvrts);
88  for (int ivrt = 0; ivrt < nvrts; ivrt++)
89  fpoints.push_back(vertex_points_[face_vertices_[face_id][ivrt]]);
90 
91  return fpoints;
92  }
93 
98  const std::vector< std::vector<int> >& face_vertices() const {
99  return face_vertices_;
100  }
101 
107  Point<D> vertex_point(int const vertex_id) const {
108  assert((vertex_id >= 0) && (unsigned(vertex_id) < vertex_points_.size()));
109  return vertex_points_[vertex_id];
110  }
111 
116  int num_vertices() const { return static_cast<int>(vertex_points_.size()); }
121  int num_faces() const { return static_cast<int>(face_vertices_.size()); }
122 
129  std::vector<double> face_moments(int face_id) const;
130 
136  Vector<D> face_normal(int face_id) const;
137 
143  std::vector<double> moments() const;
144 
145 private:
146  std::vector< Point<D> > vertex_points_; // coordinates of vertices
147  std::vector< std::vector<int> > face_vertices_; // vertices of faces
148 }; // class Polytope
149 
156 template<>
157 inline
158 std::vector<double> Polytope<2>::face_moments(int const face_id) const {
159  int nfaces = num_faces();
160  assert((face_id >= 0) && (face_id < nfaces));
161 
162  std::vector<double> fmoments(3);
163  fmoments[0] = (vertex_points_[(face_id + 1)%nfaces] - vertex_points_[face_id]).norm();
164  for (int ixy = 0; ixy < 2; ixy++)
165  fmoments[ixy + 1] = 0.5*fmoments[0]*(
166  vertex_points_[face_id][ixy] + vertex_points_[(face_id + 1)%nfaces][ixy]);
167 
168  return fmoments;
169 }
170 
178 template<>
179 inline
180 std::vector<double> Polytope<3>::face_moments(int const face_id) const {
181 
182  assert((face_id >= 0) && (face_id < num_faces()));
183 
184  std::vector<double> face_moments(4, 0.0);
185  const std::vector<int>& fvertices = face_vertices(face_id);
186  int nfvrts = static_cast<int>(fvertices.size());
187 
188  if (nfvrts == 3) {
189  face_moments[0] = 0.5*cross(vertex_points_[fvertices[1]] - vertex_points_[fvertices[0]],
190  vertex_points_[fvertices[2]] - vertex_points_[fvertices[0]]).norm();
191 
192  for (int ivrt = 0; ivrt < 3; ivrt++)
193  for (int ixyz = 0; ixyz < 3; ixyz++)
194  face_moments[ixyz + 1] += face_moments[0]*vertex_points_[fvertices[ivrt]][ixyz]/3.0;
195 
196  return face_moments;
197  }
198 
199  Point<3> gcenter;
200  for (int ivrt = 0; ivrt < nfvrts; ivrt++)
201  gcenter += vertex_points_[fvertices[ivrt]];
202  gcenter /= nfvrts;
203 
204  for (int ivrt = 0; ivrt < nfvrts; ivrt++) {
205  int ifv = fvertices[ivrt];
206  int isv = fvertices[(ivrt + 1)%nfvrts];
207 
208  double tri_size = 0.5*cross(
209  vertex_points_[isv] - vertex_points_[ifv], gcenter - vertex_points_[ifv]).norm();
210 
211  face_moments[0] += tri_size;
212  for (int ixyz = 0; ixyz < 3; ixyz++)
213  face_moments[ixyz + 1] +=
214  tri_size*(vertex_points_[ifv][ixyz] + vertex_points_[isv][ixyz] + gcenter[ixyz])/3.0;
215  }
216 
217  return face_moments;
218 }
219 
225 template<>
226 inline
228 
229  int const nfaces = num_faces();
230  assert((face_id >= 0) && (face_id < nfaces));
231 
232  int ifv = face_id, isv = (face_id + 1)%nfaces;
233  double flen = (vertex_points_[isv] - vertex_points_[ifv]).norm();
234  if (flen == 0.0)
235  return {0.0, 0.0};
236 
237  Vector<2> fnormal(
238  (vertex_points_[isv][1] - vertex_points_[ifv][1])/flen,
239  -(vertex_points_[isv][0] - vertex_points_[isv][0])/flen);
240 
241  return fnormal;
242 }
243 
251 template<>
252 inline
254 
255  assert((face_id >= 0) && (face_id < num_faces()));
256 
257  Vector<3> fnormal(0.0, 0.0, 0.0);
258  const std::vector<int>& fvertices = face_vertices(face_id);
259  int nfvrts = static_cast<int>(fvertices.size());
260  if (nfvrts == 3) {
261  fnormal = cross(vertex_points_[fvertices[1]] - vertex_points_[fvertices[0]],
262  vertex_points_[fvertices[2]] - vertex_points_[fvertices[0]]);
263  fnormal.normalize();
264 
265  return fnormal;
266  }
267 
268  std::vector<double> fmoments = face_moments(face_id);
269  if (fmoments[0] == 0.0)
270  return fnormal;
271 
272  Point<3> fcentroid;
273  for (int ixyz = 0; ixyz < 3; ixyz++)
274  fcentroid[ixyz] = fmoments[ixyz + 1]/fmoments[0];
275 
276  for (int ivrt = 0; ivrt < nfvrts; ivrt++) {
277  int ifv = fvertices[ivrt], isv = fvertices[(ivrt + 1)%nfvrts];
278  Vector<3> tri_normal = cross(
279  vertex_points_[isv] - vertex_points_[ifv],
280  fcentroid - vertex_points_[ifv]);
281  fnormal += tri_normal;
282  }
283  fnormal /= fmoments[0];
284 
285  return fnormal;
286 }
287 
293 template<>
294 inline
295 std::vector<double> Polytope<2>::moments() const {
296  std::vector<double> poly_moments(3, 0.0);
297  int nvrts = num_vertices();
298 
299  for (int ivrt = 0; ivrt < nvrts; ivrt++) {
300  int ifv = ivrt, isv = (ivrt + 1)%nvrts;
301  double cur_term = vertex_points_[ifv][0]*vertex_points_[isv][1] -
302  vertex_points_[ifv][1]*vertex_points_[isv][0];
303  poly_moments[0] += cur_term;
304  for (int ixy = 0; ixy < 2; ixy++)
305  poly_moments[ixy + 1] += cur_term*(
306  vertex_points_[ifv][ixy] + vertex_points_[isv][ixy]);
307  }
308  poly_moments[0] /= 2.0;
309  for (int ixy = 0; ixy < 2; ixy++)
310  poly_moments[ixy + 1] /= 6.0;
311 
312  return poly_moments;
313 }
314 
321 template<>
322 inline
323 std::vector<double> Polytope<3>::moments() const {
324  std::vector<double> poly_moments(4, 0.0);
325  int nfaces = num_faces();
326 
327  for (int iface = 0; iface < nfaces; iface++) {
328  std::vector<double> fmoments = face_moments(iface);
329 
330  if (fmoments[0] == 0.0)
331  continue;
332 
333  std::vector< Point<3> > face_pts = face_points(iface);
334  std::vector< std::vector<int> > itri_pts;
335 
336  int nfvrts = face_vertices_[iface].size();
337  if (nfvrts == 3)
338  itri_pts.push_back({0, 1, 2});
339  else {
340  Point<3> fcentroid;
341  for (int ixyz = 0; ixyz < 3; ixyz++)
342  fcentroid[ixyz] = fmoments[ixyz + 1]/fmoments[0];
343  face_pts.emplace_back(fcentroid);
344 
345  itri_pts.reserve(nfvrts);
346  for (int ivrt = 0; ivrt < nfvrts; ivrt++)
347  itri_pts.push_back({nfvrts, ivrt, (ivrt + 1)%nfvrts});
348  }
349 
350  for (auto&& point : itri_pts) {
351  Vector<3> vcp = cross(face_pts[point[1]] - face_pts[point[0]],
352  face_pts[point[2]] - face_pts[point[0]]);
353 
354  poly_moments[0] += dot(vcp, face_pts[point[0]].asV());
355  for (int ixyz = 0; ixyz < 3; ixyz++) {
356  for (int ivrt = 0; ivrt < 3; ivrt++) {
357  int ifv = point[ivrt], isv = point[(ivrt + 1)%3];
358  poly_moments[ixyz + 1] += vcp[ixyz]*pow(face_pts[ifv][ixyz] +
359  face_pts[isv][ixyz], 2);
360  }
361  }
362  }
363  }
364 
365  poly_moments[0] /= 6.0;
366  for (int ixyz = 0; ixyz < 3; ixyz++)
367  poly_moments[ixyz + 1] /= 48.0;
368 
369  return poly_moments;
370 }
371 
372 
373 } // namespace Wonton
374 
375 #endif // WONTON_POLYTOPE_H_
Polytope(const std::vector< Point< 3 > > &vertex_points, const std::vector< std::vector< int > > &face_vertices)
Constructor for a 3D polyhedron.
Definition: Polytope.h:45
int num_vertices() const
Number of material poly&#39;s vertices.
Definition: Polytope.h:116
const std::vector< Point< D > > & points() const
Points for all the vertices of the polytope.
Definition: Polytope.h:61
WONTON_INLINE double cross(const Vector< 2 > &a, const Vector< 2 > &b)
Cross product operator for two 2d vectors, .
Definition: Vector.h:304
std::vector< double > face_moments(int face_id) const
Moments for a face of the polytope.
Factorize a number N into D equal (or nearly equal) factors.
Definition: adaptive_refinement_mesh.h:31
std::vector< T > vector
Definition: wonton.h:285
Vector< D > face_normal(int face_id) const
Effective normal to a face of the polytope.
std::vector< double > moments() const
Moments for the polytope.
const std::vector< std::vector< int > > & face_vertices() const
Indices of vertices for all the faces of the polytope.
Definition: Polytope.h:98
Represents a point in an N-dimensional space.
Definition: Point.h:50
std::vector< Point< D > > face_points(int const face_id) const
Coordinates of vertices of the polytope&#39;s face in counter-clockwise order (i.e. so that the normal to...
Definition: Polytope.h:82
Polytope(const std::vector< Point< 2 > > &vertex_points)
Constructor for a 2D polygon.
Definition: Polytope.h:28
WONTON_INLINE void normalize()
Convert this Vector into a unit Vector.
Definition: Vector.h:180
Point< D > vertex_point(int const vertex_id) const
Coordinates of a polytope&#39;s vertex.
Definition: Polytope.h:107
const std::vector< int > & face_vertices(int const face_id) const
Indices of vertices of the polytope&#39;s face in counter-clockwise order (i.e. so that the normal to the...
Definition: Polytope.h:70
~Polytope()=default
Definition: Polytope.h:21
int num_faces() const
Number of material poly&#39;s faces.
Definition: Polytope.h:121
Represents a vector in N-dimensional space.
Definition: Vector.h:40
WONTON_INLINE double dot(const Vector< D > &a, const Vector< D > &b)
Dot product of two vectors, .
Definition: Vector.h:248