3 #include <Caribou/config.h>
4 #include <Caribou/constants.h>
5 #include <Caribou/Geometry/Element.h>
6 #include <Caribou/Geometry/Triangle.h>
10 namespace caribou::geometry {
17 template<
typename Derived>
22 using LocalCoordinates =
typename Base::LocalCoordinates;
23 using WorldCoordinates =
typename Base::WorldCoordinates;
25 using GaussNode =
typename Base::GaussNode;
27 template <UNSIGNED_INTEGER_TYPE Dim>
28 using Vector =
typename Base::template Vector<Dim>;
30 template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
31 using Matrix =
typename Base::template Matrix<Rows, Cols>;
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;
39 static_assert(Dimension == 3,
"Hexahedrons can only be of dimension 3.");
41 using Size = Vector<3>;
42 using Rotation = Matrix<3,3>;
70 inline auto rotation() const -> const Rotation & {
75 inline auto size() const -> const Size & {
80 inline auto world_coordinates(
const LocalCoordinates & coordinates)
const -> WorldCoordinates {
85 inline auto local_coordinates(
const WorldCoordinates & coordinates)
const -> LocalCoordinates {
86 return (
p_R.transpose()*(coordinates -
p_center)).cwiseQuotient(
p_H / 2.);
90 inline auto contains(
const WorldCoordinates & coordinates)
const ->
bool
113 LocalCoordinates
nodes[3];
114 for (UNSIGNED_INTEGER_TYPE i = 0; i < 3; ++i) {
118 return intersects_local_polygon<3>(
nodes, t.normal(), eps);
123 friend struct Element<Derived>;
125 inline auto get_number_of_nodes()
const {
return NumberOfNodesAtCompileTime;}
127 inline auto get_number_of_gauss_nodes()
const {
return NumberOfGaussNodesAtCompileTime;}
128 inline auto get_center()
const {
return p_center;};
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);
140 auto self() -> Derived& {
return *
static_cast<Derived*
>(
this); }
141 auto self()
const ->
const Derived& {
return *
static_cast<const Derived*
>(
this); }
149 inline auto intersects_local_segment(LocalCoordinates v0, LocalCoordinates v1,
const FLOATING_POINT_TYPE & eps)
const -> bool;
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;
169 template<
typename Derived>
172 const auto edge = (v1 - v0);
173 INTEGER_TYPE edge_signs[3];
175 for (UNSIGNED_INTEGER_TYPE i = 0; i < 3; ++i) {
176 edge_signs[i] = (edge[i] < 0) ? -1 : 1;
179 for (UNSIGNED_INTEGER_TYPE i = 0; i < 3; ++i) {
181 if (v0[i] * edge_signs[i] > 1+eps)
return false;
182 if (v1[i] * edge_signs[i] < -1-eps)
return false;
186 for (UNSIGNED_INTEGER_TYPE i = 0; i < 3; ++i) {
187 FLOATING_POINT_TYPE rhomb_normal_dot_v0, rhomb_normal_dot_cubedge;
189 const UNSIGNED_INTEGER_TYPE iplus1 = (i + 1) % 3;
190 const UNSIGNED_INTEGER_TYPE iplus2 = (i + 2) % 3;
192 rhomb_normal_dot_v0 = edge[iplus2] * v0[iplus1] -
193 edge[iplus1] * v0[iplus2];
195 rhomb_normal_dot_cubedge = edge[iplus2] * edge_signs[iplus1] +
196 edge[iplus1] * edge_signs[iplus2];
198 const auto r = (rhomb_normal_dot_v0*rhomb_normal_dot_v0) - (rhomb_normal_dot_cubedge*rhomb_normal_dot_cubedge);
206 #define seg_contains_point(a,b,x) (((b)>(x)) - ((a)>(x)))
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 {
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))
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);
228 const FLOATING_POINT_TYPE t = polynormal.dot(nodes[0]) / polynormal.dot(best_diagonal);
229 if (!IN_CLOSED_INTERVAL(-1-eps, t, 1+eps))
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;
239 zaxis = (abspolynormal[1] > abspolynormal[2]) ? 1 : 2;
241 if (polynormal[zaxis] < 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];
255 if (
const int xdirection = seg_contains_point(p1[xaxis]-eps, p2[xaxis]+eps, p[xaxis]))
257 if (seg_contains_point(p1[yaxis]-eps, p2[yaxis]+eps, p[yaxis]))
259 if (xdirection * (p[xaxis]-p1[xaxis])*(p2[yaxis]-p1[yaxis]) <=
260 xdirection * (p[yaxis]-p1[yaxis])*(p2[xaxis]-p1[xaxis]))
265 if (p2[yaxis] <= p[yaxis])
275 #undef seg_contains_point