Caribou
BaseTriangle.h
1 #pragma once
2 
3 #include <Caribou/config.h>
4 #include <Caribou/constants.h>
5 #include <Caribou/Geometry/Element.h>
6 #include <Eigen/Core>
7 
8 namespace caribou::geometry {
9 
10 template<typename Derived>
11 struct BaseTriangle : public Element<Derived> {
12  // Types
13  using Base = Element<Derived>;
14 
15  using LocalCoordinates = typename Base::LocalCoordinates;
16  using WorldCoordinates = typename Base::WorldCoordinates;
17 
18  using GaussNode = typename Base::GaussNode;
19 
20  template <UNSIGNED_INTEGER_TYPE Dim>
21  using Vector = typename Base::template Vector<Dim>;
22 
23  template <UNSIGNED_INTEGER_TYPE Rows, UNSIGNED_INTEGER_TYPE Cols>
24  using Matrix = typename Base::template Matrix<Rows, Cols>;
25 
26  // Constants
27  static constexpr auto CanonicalDimension = Base::CanonicalDimension;
28  static constexpr auto Dimension = Base::Dimension;
29  static constexpr auto NumberOfNodesAtCompileTime = Base::NumberOfNodesAtCompileTime;
30  static constexpr auto NumberOfGaussNodesAtCompileTime = Base::NumberOfGaussNodesAtCompileTime;
31 
32  static_assert(Dimension == 2 or Dimension == 3, "Triangles can only be of dimension 2 or 3.");
33 
35  BaseTriangle() = default;
36 
38  template<typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
39  explicit BaseTriangle(Eigen::EigenBase<EigenType> & nodes) :p_nodes(nodes.derived().template cast<typename Base::Scalar>()) {}
40 
42  template<typename EigenType, REQUIRES(EigenType::RowsAtCompileTime == NumberOfNodesAtCompileTime)>
43  explicit BaseTriangle(const Eigen::EigenBase<EigenType> & nodes) :p_nodes(nodes.derived().template cast<typename Base::Scalar>()) {}
44 
46  template <
47  typename ...Nodes,
48  REQUIRES(NumberOfNodesAtCompileTime == sizeof...(Nodes)+1)
49  >
50  explicit BaseTriangle(const WorldCoordinates & first_node, Nodes&&...remaining_nodes)
51  {
52  construct_from_nodes<0>(first_node, std::forward<Nodes>(remaining_nodes)...);
53  }
54 
55  // Public methods common to all triangle types
56 
62  inline auto normal() const noexcept -> WorldCoordinates {
63  static_assert(Dimension == 3, "Can only get the normal of a triangle in a 3D world");
64  const WorldCoordinates v1 = self().node(1) - self().node(0);
65  const WorldCoordinates v2 = self().node(2) - self().node(0);
66 
67  return v1.cross(v2).normalized();
68  }
69 
74  inline auto edges() const {
75  return self().get_boundary_elements_nodes();
76  }
77 
78 private:
79  // Implementations
80  friend struct Element<Derived>;
81  [[nodiscard]]
82  inline auto get_number_of_nodes() const {return NumberOfNodesAtCompileTime;}
83  inline auto get_number_of_gauss_nodes() const {return NumberOfGaussNodesAtCompileTime;}
84  inline auto get_node(const UNSIGNED_INTEGER_TYPE & index) const {return WorldCoordinates(p_nodes.row(index));};
85  inline auto get_nodes() const -> const auto & {return p_nodes;};
86  inline auto get_center() const {return Base::world_coordinates(LocalCoordinates({1/3., 1/3.}));};
87  inline auto get_number_of_boundary_elements() const -> UNSIGNED_INTEGER_TYPE {return 3;};
88  inline auto get_contains_local(const LocalCoordinates & xi, const FLOATING_POINT_TYPE & eps) const -> bool {
89  const auto & u = xi[0];
90  const auto & v = xi[1];
91  return (u > -eps) and (v > -eps) and (1 - u - v > -eps);
92  }
93 
94  auto self() -> Derived& { return *static_cast<Derived*>(this); }
95  auto self() const -> const Derived& { return *static_cast<const Derived*>(this); }
96 
97  template <size_t index, typename ...Nodes, REQUIRES(sizeof...(Nodes) >= 1)>
98  inline
99  void construct_from_nodes(const WorldCoordinates & first_node, Nodes&&...remaining_nodes) {
100  p_nodes.row(index) = first_node;
101  construct_from_nodes<index+1>(std::forward<Nodes>(remaining_nodes)...);
102  }
103 
104  template <size_t index>
105  inline
106  void construct_from_nodes(const WorldCoordinates & last_node) {
107  p_nodes.row(index) = last_node;
108  }
109 protected:
110  Matrix<NumberOfNodesAtCompileTime, Dimension> p_nodes;
111 };
112 
113 }
caribou::geometry::Element< Derived >::world_coordinates
auto world_coordinates(const LocalCoordinates &coordinates) const -> WorldCoordinates
Get the world coordinates of a point from its local coordinates.
Definition: Element.h:157
caribou::geometry::Element
Definition: Element.h:28
caribou::geometry::BaseTriangle::BaseTriangle
BaseTriangle(const Eigen::EigenBase< EigenType > &nodes)
Constructor from an Eigen matrix containing the positions of the triangle's nodes.
Definition: BaseTriangle.h:43
caribou::geometry::BaseTriangle::BaseTriangle
BaseTriangle(const WorldCoordinates &first_node, Nodes &&...remaining_nodes)
Constructor from a serie of nodes.
Definition: BaseTriangle.h:50
caribou::geometry::BaseTriangle::edges
auto edges() const
Get the list of node indices of the edges.
Definition: BaseTriangle.h:74
caribou::geometry::BaseTriangle
Definition: BaseTriangle.h:11
caribou::geometry::Element< Derived >::nodes
auto nodes() const
Get the set of nodes.
Definition: Element.h:67
caribou::geometry::BaseTriangle::normal
auto normal() const noexcept -> WorldCoordinates
Get the vector normal to the triangle's surface.
Definition: BaseTriangle.h:62
caribou::geometry::Element< Derived >::node
auto node(const UNSIGNED_INTEGER_TYPE &index) const
Get the Node at given index.
Definition: Element.h:64
caribou::geometry::BaseTriangle::BaseTriangle
BaseTriangle(Eigen::EigenBase< EigenType > &nodes)
Constructor from an Eigen matrix containing the positions of the triangle's nodes.
Definition: BaseTriangle.h:39
caribou::geometry::BaseTriangle::BaseTriangle
BaseTriangle()=default
Default empty constructor.