Caribou
BaseRectangularHexahedron.h
1 #pragma once
2 
3 #include <Caribou/config.h>
4 #include <Caribou/constants.h>
5 #include <Caribou/Geometry/Element.h>
6 #include <Caribou/Geometry/Triangle.h>
7 #include <Eigen/Core>
8 
9 
10 namespace caribou::geometry {
11 
17 template<typename Derived>
18 struct BaseRectangularHexahedron : public Element<Derived> {
19  // Types
20  using Base = Element<Derived>;
21 
22  using LocalCoordinates = typename Base::LocalCoordinates;
23  using WorldCoordinates = typename Base::WorldCoordinates;
24 
25  using GaussNode = typename Base::GaussNode;
26 
27  template <UNSIGNED_INTEGER_TYPE Dim>
28  using Vector = typename Base::template Vector<Dim>;
29 
30  template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
31  using Matrix = typename Base::template Matrix<Rows, Cols>;
32 
33  // Constants
34  static constexpr auto CanonicalDimension = Base::CanonicalDimension;
35  static constexpr auto Dimension = Base::Dimension;
36  static constexpr auto NumberOfNodesAtCompileTime = Base::NumberOfNodesAtCompileTime;
37  static constexpr auto NumberOfGaussNodesAtCompileTime = Base::NumberOfGaussNodesAtCompileTime;
38 
39  static_assert(Dimension == 3, "Hexahedrons can only be of dimension 3.");
40 
41  using Size = Vector<3>;
42  using Rotation = Matrix<3,3>;
43 
45  BaseRectangularHexahedron() : p_center(0, 0, 0), p_H(2,2,2), p_R(Rotation::Identity()) {}
46 
48  explicit BaseRectangularHexahedron(WorldCoordinates center) : p_center(center), p_H(Size::Constant(2)), p_R(Rotation::Identity()) {}
49 
51  BaseRectangularHexahedron(WorldCoordinates center, Size H) : p_center(center), p_H(H), p_R(Rotation::Identity()) {}
52 
54  BaseRectangularHexahedron(WorldCoordinates center, Rotation R) : p_center(center), p_H(Size::Constant(2)), p_R(R) {}
55 
57  BaseRectangularHexahedron(WorldCoordinates center, Size H, Rotation R) : p_center(center), p_H(H), p_R(R) {}
58 
59  // Public methods common to all rectangular hexahedral types
60 
65  inline auto faces() const {
66  return self().boundary_elements_node_indices();
67  }
68 
70  inline auto rotation() const -> const Rotation & {
71  return p_R;
72  };
73 
75  inline auto size() const -> const Size & {
76  return p_H;
77  };
78 
80  inline auto world_coordinates(const LocalCoordinates & coordinates) const -> WorldCoordinates {
81  return p_center + p_R * (coordinates.cwiseProduct(p_H / 2.));
82  }
83 
85  inline auto local_coordinates(const WorldCoordinates & coordinates) const -> LocalCoordinates {
86  return (p_R.transpose()*(coordinates - p_center)).cwiseQuotient(p_H / 2.);
87  }
88 
90  inline auto contains(const WorldCoordinates & coordinates) const -> bool
91  {
92  const auto c = local_coordinates(coordinates);
93  return self().contains_local(c);
94  }
95 
101  [[nodiscard]]
102  inline auto intersects(const Segment<_3D, Linear> & segment, const FLOATING_POINT_TYPE eps=EPSILON) const -> bool {
103  return intersects_local_segment(local_coordinates(segment.node(0)), local_coordinates(segment.node(1)), eps);
104  }
105 
111  [[nodiscard]]
112  inline auto intersects(const Triangle<_3D, Linear> & t, const FLOATING_POINT_TYPE eps=1e-10) const -> bool {
113  LocalCoordinates nodes[3];
114  for (UNSIGNED_INTEGER_TYPE i = 0; i < 3; ++i) {
115  nodes[i] = local_coordinates(t.node(i));
116  }
117 
118  return intersects_local_polygon<3>(nodes, t.normal(), eps);
119  }
120 
121 private:
122  // Implementations
123  friend struct Element<Derived>;
124  [[nodiscard]]
125  inline auto get_number_of_nodes() const {return NumberOfNodesAtCompileTime;}
126  [[nodiscard]]
127  inline auto get_number_of_gauss_nodes() const {return NumberOfGaussNodesAtCompileTime;}
128  inline auto get_center() const {return p_center;};
129  [[nodiscard]]
130  inline auto get_number_of_boundary_elements() const -> UNSIGNED_INTEGER_TYPE {return 6;};
131  inline auto get_contains_local(const LocalCoordinates & xi, const FLOATING_POINT_TYPE & eps) const -> bool {
132  const auto & u = xi[0];
133  const auto & v = xi[1];
134  const auto & w = xi[2];
135  return IN_CLOSED_INTERVAL(-1-eps, u, 1+eps) and
136  IN_CLOSED_INTERVAL(-1-eps, v, 1+eps) and
137  IN_CLOSED_INTERVAL(-1-eps, w, 1+eps);
138  }
139 
140  auto self() -> Derived& { return *static_cast<Derived*>(this); }
141  auto self() const -> const Derived& { return *static_cast<const Derived*>(this); }
142 
148  [[nodiscard]]
149  inline auto intersects_local_segment(LocalCoordinates v0, LocalCoordinates v1, const FLOATING_POINT_TYPE & eps) const -> bool;
150 
160  template <int NNodes>
161  inline auto intersects_local_polygon(const LocalCoordinates nodes[NNodes], const Vector<3> & polynormal, const FLOATING_POINT_TYPE & eps) const -> bool;
162 
163 protected:
164  WorldCoordinates p_center;
165  Size p_H;
166  Rotation p_R;
167 };
168 
169 template<typename Derived>
170 auto BaseRectangularHexahedron<Derived>::intersects_local_segment(LocalCoordinates v0, LocalCoordinates v1, const FLOATING_POINT_TYPE & eps) const -> bool
171 {
172  const auto edge = (v1 - v0);
173  INTEGER_TYPE edge_signs[3];
174 
175  for (UNSIGNED_INTEGER_TYPE i = 0; i < 3; ++i) {
176  edge_signs[i] = (edge[i] < 0) ? -1 : 1;
177  }
178 
179  for (UNSIGNED_INTEGER_TYPE i = 0; i < 3; ++i) {
180 
181  if (v0[i] * edge_signs[i] > 1+eps) return false;
182  if (v1[i] * edge_signs[i] < -1-eps) return false;
183  }
184 
185 
186  for (UNSIGNED_INTEGER_TYPE i = 0; i < 3; ++i) {
187  FLOATING_POINT_TYPE rhomb_normal_dot_v0, rhomb_normal_dot_cubedge;
188 
189  const UNSIGNED_INTEGER_TYPE iplus1 = (i + 1) % 3;
190  const UNSIGNED_INTEGER_TYPE iplus2 = (i + 2) % 3;
191 
192  rhomb_normal_dot_v0 = edge[iplus2] * v0[iplus1] -
193  edge[iplus1] * v0[iplus2];
194 
195  rhomb_normal_dot_cubedge = edge[iplus2] * edge_signs[iplus1] +
196  edge[iplus1] * edge_signs[iplus2];
197 
198  const auto r = (rhomb_normal_dot_v0*rhomb_normal_dot_v0) - (rhomb_normal_dot_cubedge*rhomb_normal_dot_cubedge);
199  if (r > eps)
200  return false;
201  }
202 
203  return true;
204 }
205 
206 #define seg_contains_point(a,b,x) (((b)>(x)) - ((a)>(x)))
207 
208 template<typename Derived>
209 template <int NNodes>
210 inline auto BaseRectangularHexahedron<Derived>::intersects_local_polygon(const LocalCoordinates nodes[NNodes], const Vector<3> & polynormal, const FLOATING_POINT_TYPE & eps) const -> bool {
211 
212  // Check if any edges of the polygon intersect the hexa
213  for (UNSIGNED_INTEGER_TYPE i = 0; i < NNodes; ++i) {
214  const auto & p1 = nodes[i];
215  const auto & p2 = nodes[(i+1)%NNodes];
216  if (intersects_local_segment(p1, p2, eps))
217  return true;
218  }
219 
220  // Check that if the polygon's plane intersect the cube diagonal that is the closest of being perpendicular to the
221  // plane of the polygon.
222  Vector<3> best_diagonal;
223  best_diagonal << (((polynormal[0]) < 0) ? -1 : 1),
224  (((polynormal[1]) < 0) ? -1 : 1),
225  (((polynormal[2]) < 0) ? -1 : 1);
226 
227  // Check if the intersection point between the two planes lies inside the cube
228  const FLOATING_POINT_TYPE t = polynormal.dot(nodes[0]) / polynormal.dot(best_diagonal);
229  if (!IN_CLOSED_INTERVAL(-1-eps, t, 1+eps))
230  return false;
231 
232  // Check if the intersection point between the two planes lies inside the polygon
233  LocalCoordinates p = best_diagonal * t;
234  const LocalCoordinates abspolynormal = polynormal.array().abs();
235  int zaxis, xaxis, yaxis;
236  if (abspolynormal[0] > abspolynormal[1])
237  zaxis = (abspolynormal[0] > abspolynormal[2]) ? 0 : 2;
238  else
239  zaxis = (abspolynormal[1] > abspolynormal[2]) ? 1 : 2;
240 
241  if (polynormal[zaxis] < 0) {
242  xaxis = (zaxis+2)%3;
243  yaxis = (zaxis+1)%3;
244  }
245  else {
246  xaxis = (zaxis+1)%3;
247  yaxis = (zaxis+2)%3;
248  }
249 
250  int count = 0;
251  for (UNSIGNED_INTEGER_TYPE i = 0; i < NNodes; ++i) {
252  const auto & p1 = nodes[i];
253  const auto & p2 = nodes[(i+1)%NNodes];
254 
255  if (const int xdirection = seg_contains_point(p1[xaxis]-eps, p2[xaxis]+eps, p[xaxis]))
256  {
257  if (seg_contains_point(p1[yaxis]-eps, p2[yaxis]+eps, p[yaxis]))
258  {
259  if (xdirection * (p[xaxis]-p1[xaxis])*(p2[yaxis]-p1[yaxis]) <=
260  xdirection * (p[yaxis]-p1[yaxis])*(p2[xaxis]-p1[xaxis]))
261  count += xdirection;
262  }
263  else
264  {
265  if (p2[yaxis] <= p[yaxis])
266  count += xdirection;
267  }
268  }
269 
270  }
271 
272  return (count != 0);
273 }
274 
275 #undef seg_contains_point
276 
277 }
caribou::geometry::BaseRectangularHexahedron
Base class for rectangular hexahedral elements.
Definition: BaseRectangularHexahedron.h:18
caribou::geometry::Element< Derived >::boundary_elements_node_indices
auto boundary_elements_node_indices() const -> const auto &
Get the list of node indices of the boundary elements.
Definition: Element.h:100
caribou::geometry::BaseRectangularHexahedron::BaseRectangularHexahedron
BaseRectangularHexahedron(WorldCoordinates center, Size H)
Constructor by specifying the center point and the size (hx, hy, hz)
Definition: BaseRectangularHexahedron.h:51
caribou::geometry::Element
Definition: Element.h:28
caribou::geometry::BaseRectangularHexahedron::BaseRectangularHexahedron
BaseRectangularHexahedron(WorldCoordinates center)
Constructor by specifying the center point.
Definition: BaseRectangularHexahedron.h:48
caribou::geometry::BaseRectangularHexahedron::local_coordinates
auto local_coordinates(const WorldCoordinates &coordinates) const -> LocalCoordinates
Get the local coordinates of a point from its world coordinates.
Definition: BaseRectangularHexahedron.h:85
caribou::geometry::BaseRectangularHexahedron::size
auto size() const -> const Size &
Get the size (hx, hy) of the quad.
Definition: BaseRectangularHexahedron.h:75
caribou::geometry::Element< Derived >::nodes
auto nodes() const
Get the set of nodes.
Definition: Element.h:67
caribou::geometry::BaseRectangularHexahedron::intersects
auto intersects(const Triangle< _3D, Linear > &t, const FLOATING_POINT_TYPE eps=1e-10) const -> bool
Test if the cube intersects the given 3D triangle (in world coordinates)
Definition: BaseRectangularHexahedron.h:112
caribou::geometry::BaseRectangularHexahedron::p_R
Rotation p_R
Rotation matrix (a.k.a. the local coordinates frame) at the center of the hexahedron.
Definition: BaseRectangularHexahedron.h:166
caribou::geometry::BaseRectangularHexahedron::faces
auto faces() const
Get the list of node indices of the faces.
Definition: BaseRectangularHexahedron.h:65
caribou::geometry::BaseRectangularHexahedron::intersects
auto intersects(const Segment< _3D, Linear > &segment, const FLOATING_POINT_TYPE eps=EPSILON) const -> bool
Test if the cube intersects the given 3D segment (in world coordinates)
Definition: BaseRectangularHexahedron.h:102
caribou::geometry::BaseRectangularHexahedron::rotation
auto rotation() const -> const Rotation &
Get the rotation frame of the quad.
Definition: BaseRectangularHexahedron.h:70
caribou::geometry::BaseRectangularHexahedron::BaseRectangularHexahedron
BaseRectangularHexahedron(WorldCoordinates center, Size H, Rotation R)
Constructor by specifying the center point, the size (hx, hy, hz) and the rotation.
Definition: BaseRectangularHexahedron.h:57
caribou::geometry::BaseRectangularHexahedron::contains
auto contains(const WorldCoordinates &coordinates) const -> bool
Returns true if the given world coordinates are within the hexahedron's boundaries,...
Definition: BaseRectangularHexahedron.h:90
caribou::geometry::Segment
Definition: Segment.h:10
caribou::geometry::BaseRectangularHexahedron::BaseRectangularHexahedron
BaseRectangularHexahedron()
Default empty constructor.
Definition: BaseRectangularHexahedron.h:45
caribou::geometry::BaseRectangularHexahedron::p_center
WorldCoordinates p_center
Position of the center point of the hexahedron.
Definition: BaseRectangularHexahedron.h:164
caribou::geometry::BaseRectangularHexahedron::BaseRectangularHexahedron
BaseRectangularHexahedron(WorldCoordinates center, Rotation R)
Constructor by specifying the center point and the rotation.
Definition: BaseRectangularHexahedron.h:54
caribou::geometry::Element< Derived >::contains_local
auto contains_local(const LocalCoordinates &xi, const FLOATING_POINT_TYPE &eps=1e-10) const -> bool
Return true if the element contains the point located at the given local coordinates.
Definition: Element.h:272
caribou::geometry::BaseRectangularHexahedron::world_coordinates
auto world_coordinates(const LocalCoordinates &coordinates) const -> WorldCoordinates
Get the world coordinates of a point from its local coordinates.
Definition: BaseRectangularHexahedron.h:80
caribou::geometry::Triangle
Definition: Triangle.h:12
caribou::geometry::BaseRectangularHexahedron::p_H
Size p_H
Size of the hexahedron {hx, hy, hz}.
Definition: BaseRectangularHexahedron.h:165
caribou::geometry::Element< Derived >::center
auto center() const -> WorldCoordinates
Get the position at the center of the element.
Definition: Element.h:154