Caribou
FictitiousGrid.h
1 #pragma once
2 
3 #include <sofa/version.h>
4 #include <sofa/core/objectmodel/BaseObject.h>
5 #include <sofa/defaulttype/Vec.h>
6 #include <sofa/defaulttype/VecTypes.h>
7 #include <sofa/core/topology/BaseMeshTopology.h>
8 
9 #include <Caribou/Geometry/RectangularQuad.h>
10 #include <Caribou/Geometry/RectangularHexahedron.h>
11 #include <Caribou/Topology/Grid/Grid.h>
12 #include <Caribou/config.h>
13 
14 #include <SofaCaribou/Topology/IsoSurface.h>
15 
16 #include <memory>
17 #include <exception>
18 #include <bitset>
19 #include <functional>
20 #include <sstream>
21 
22 #if (defined(SOFA_VERSION) && SOFA_VERSION < 201299)
23 namespace sofa { using Index = unsigned int; }
24 #endif
25 
26 namespace SofaCaribou::topology {
27 
28 using namespace sofa::core::objectmodel;
29 
30 using sofa::defaulttype::Vec2Types;
31 using sofa::defaulttype::Vec3Types;
32 
33 template <typename DataTypes>
34 class FictitiousGrid : public virtual BaseObject
35 {
36 public:
37 
38  SOFA_CLASS(SOFA_TEMPLATE(FictitiousGrid, DataTypes), BaseObject);
39 
40  static constexpr unsigned char Dimension = DataTypes::spatial_dimensions;
41 
42  // --------------------
43  // Caribou data aliases
44  // --------------------
45  using Index = std::size_t;
46  using Int = INTEGER_TYPE;
47  using Float = FLOATING_POINT_TYPE;
48 
49  // -----------------
50  // Sofa data aliases
51  // -----------------
52  using SofaFloat = typename DataTypes::Real;
53  using SofaVecInt = sofa::defaulttype::Vec<Dimension, UNSIGNED_INTEGER_TYPE>;
54  using SofaVecFloat = sofa::defaulttype::Vec<Dimension, SofaFloat>;
55  using Coord = typename DataTypes::Coord;
56  using SofaVecCoord = sofa::helper::vector<Coord>;
57  using ElementId = sofa::Index;
58  using VecElementId = sofa::helper::vector<ElementId>;
59  using SofaHexahedron = sofa::core::topology::BaseMeshTopology::Hexahedron;
60  using SofaQuad = sofa::core::topology::BaseMeshTopology::Quad;
61  using SofaTriangle = sofa::core::topology::BaseMeshTopology::Triangle;
62  using SofaEdge = sofa::core::topology::BaseMeshTopology::Edge;
63 
64  // -----------------
65  // Grid data aliases
66  // -----------------
68  using NodeIndex = typename GridType::NodeIndex;
69  using CellIndex = typename GridType::CellIndex;
70  using Dimensions = typename GridType::Dimensions;
71  using Subdivisions = typename GridType::Subdivisions;
72  using LocalCoordinates = typename GridType::LocalCoordinates;
73  using WorldCoordinates = typename GridType::WorldCoordinates;
74  using GridCoordinates = typename GridType::GridCoordinates;
75  using CellSet = typename GridType::CellSet;
76  using CellElement = typename GridType::Element;
77 
78  // -----------------
79  // Structures
80  // -----------------
81  enum class Type : INTEGER_TYPE {
82  Undefined = std::numeric_limits<INTEGER_TYPE>::lowest(),
83  Inside = (unsigned) 1 << (unsigned) 0,
84  Outside = (unsigned) 1 << (unsigned) 1,
85  Boundary = (unsigned) 1 << (unsigned) 2
86  };
87 
89  struct CellData {
90  CellData(const Type & t, const Float& w, const int & r, const bool &b)
91  : type(t), weight(w), region_id(r), boundary_of_region(b) {}
92  Type type = Type::Undefined;
93  Float weight = 0.; // 1 for full cell, 1/4 (resp. 1/8) for the first level of subdivision in 2D (resp. 3D), etc.
94  int region_id = -1;
95  bool boundary_of_region = false; // True if the leaf-cell makes the boundary between its region and another one
96  };
97 
99  struct Cell {
100  Cell * parent = nullptr;
101  CellIndex index = 0; // Index relative to the parent cell
102  std::unique_ptr<CellData> data; // Data is only stored on leaf cells
103  std::unique_ptr<std::array<Cell,(unsigned) 1 << Dimension>> childs;
104 
105  inline bool is_leaf() const {return childs.get() == nullptr;}
106  };
107 
110  struct Region {
111  Type type = Type::Undefined;
112  std::vector<Cell*> cells; // Leaf cells filling the region
113  };
114 
115  // -------
116  // Aliases
117  // -------
118 
119  template <typename ObjectType>
120  using Link = SingleLink<FictitiousGrid<DataTypes>, ObjectType, BaseLink::FLAG_STRONGLINK>;
121 
122  // ----------------
123  // Public functions
124  // ----------------
125  FictitiousGrid();
126 
128  virtual void
129  create_grid();
130 
132  inline UNSIGNED_INTEGER_TYPE
133  number_of_cells() const {
134  return p_cell_index_in_grid.size();
135  }
136 
138  inline UNSIGNED_INTEGER_TYPE
139  number_of_nodes() const {
140  return p_node_index_in_grid.size();
141  }
142 
144  inline UNSIGNED_INTEGER_TYPE
146  return d_number_of_subdivision.getValue();
147  }
148 
153  std::vector<Cell *>
154  get_neighbors(const Cell * cell) const;
155 
161  std::vector<Cell *>
162  get_neighbors(const Cell * cell, UNSIGNED_INTEGER_TYPE axis, INTEGER_TYPE direction) const;
163 
171  std::vector<std::pair<LocalCoordinates, FLOATING_POINT_TYPE>>
172  get_gauss_nodes_of_cell(const CellIndex & sparse_cell_index) const;
173 
185  std::vector<std::pair<LocalCoordinates, FLOATING_POINT_TYPE>>
186  get_gauss_nodes_of_cell(const CellIndex & sparse_cell_index, const UNSIGNED_INTEGER_TYPE level) const;
187 
191  inline CellElement
192  get_cell_element(const CellIndex & sparse_cell_index) const {
193  const auto cell_index = p_cell_index_in_grid[sparse_cell_index];
194  return std::move(p_grid->cell_at(cell_index));
195  }
196 
200  inline const SofaHexahedron &
201  get_node_indices_of(const CellIndex & sparse_cell_index) const {
202  return d_hexahedrons.getValue().at(sparse_cell_index);
203  }
204 
208  inline Type
209  get_type_at(const WorldCoordinates & p) const;
210 
229  inline std::map<FLOATING_POINT_TYPE, std::vector<CellIndex>>
230  cell_volume_ratio_distribution(UNSIGNED_INTEGER_TYPE number_of_decimals=0) const;
231 
232  // ---------------------
233  // SOFA METHOD OVERRIDES
234  // ---------------------
235 
236  void init() override;
237  void draw(const sofa::core::visual::VisualParams* vparams) override;
238 
239  void computeBBox(const sofa::core::ExecParams*, bool onlyVisible) override {
240  if( !onlyVisible )
241  return;
242 
243  if (Dimension == 2) {
244  const Float min[3] = {
245  d_min.getValue()[0], d_min.getValue()[1], -1
246  };
247  const Float max[3] = {
248  d_max.getValue()[0], d_max.getValue()[1], +1
249  };
250  this->f_bbox.setValue(sofa::defaulttype::TBoundingBox<Float>(min, max));
251  } else {
252  this->f_bbox.setValue(sofa::defaulttype::TBoundingBox<Float>(
253  d_min.getValue().array(),d_max.getValue().array()));
254  }
255  }
256 
257  std::string getTemplateName() const override {
258  return templateName(this);
259  }
260 
261  static std::string templateName(const FictitiousGrid<DataTypes>* = nullptr) {
262  return DataTypes::Name();
263  }
264 
265 private:
266  virtual void tag_intersected_cells_from_implicit_surface();
267  virtual void tag_intersected_cells();
268  virtual void tag_outside_cells();
269  virtual void tag_inside_cells();
270  virtual void subdivide_intersected_cells();
271  virtual void create_regions_from_same_type_cells();
272  virtual void create_sparse_grid();
273  virtual void populate_drawing_vectors();
274  virtual void validate_grid();
275 
276  std::array<CellElement, (unsigned) 1 << Dimension> get_subcells_elements(const CellElement & e) const;
277  std::vector<Cell *> get_leaf_cells(const Cell & c) const {return std::move(get_leaf_cells(&c));}
278  std::vector<Cell *> get_leaf_cells(const Cell * c) const;
279  inline FLOATING_POINT_TYPE get_cell_weight(const Cell & c) const;
280 
281 private:
282  // ------------------
283  // Input data members
284  // ------------------
285  Data<SofaVecInt> d_n;
286  Data<SofaVecFloat> d_min;
287  Data<SofaVecFloat> d_max;
288  Data<UNSIGNED_INTEGER_TYPE> d_number_of_subdivision;
289  Data<Float> d_volume_threshold;
290  Link<IsoSurface<DataTypes>> d_iso_surface;
291  Data<bool> d_draw_boundary_cells;
292  Data<bool> d_draw_outside_cells;
293  Data<bool> d_draw_inside_cells;
294  Data<double> d_draw_scale;
295 
296  Data< SofaVecCoord > d_surface_positions;
297 
299  Data<sofa::helper::vector<SofaEdge> > d_surface_edges;
300 
302  Data<sofa::helper::vector<SofaTriangle> > d_surface_triangles;
303 
304  // -------------------
305  // Output data members
306  // -------------------
308  Data< SofaVecCoord > d_positions;
309 
311  Data < sofa::helper::vector<SofaQuad> > d_quads;
312 
314  Data < sofa::helper::vector<SofaHexahedron> > d_hexahedrons;
315 
316 
317  // ---------------
318  // Private members
319  // ---------------
322  std::unique_ptr<GridType> p_grid;
323 
325  std::vector<Type> p_cells_types;
326 
328  std::vector<std::vector<Index>> p_triangles_of_cell;
329 
331  std::vector<Cell> p_cells;
332 
334  std::vector<Region> p_regions;
335 
338  std::vector<INTEGER_TYPE> p_node_index_in_sparse_grid;
339 
341  std::vector<UNSIGNED_INTEGER_TYPE> p_node_index_in_grid;
342 
345  std::vector<INTEGER_TYPE> p_cell_index_in_sparse_grid;
346 
348  std::vector<UNSIGNED_INTEGER_TYPE> p_cell_index_in_grid;
349 
351  std::vector<sofa::defaulttype::Vector3> p_drawing_nodes_vector;
352 
354  std::vector<sofa::defaulttype::Vector3> p_drawing_edges_vector;
355 
357  std::vector<std::vector<sofa::defaulttype::Vector3>> p_drawing_subdivided_edges_vector;
358 
360  std::vector<std::vector<sofa::defaulttype::Vector3>> p_drawing_cells_vector;
361 
362  // ----------------------
363  // Private static members
364  // ----------------------
366  static const GridCoordinates subcell_coordinates[(unsigned) 1 << Dimension];
367 
368 };
369 
370 template<> const FictitiousGrid<Vec2Types>::GridCoordinates FictitiousGrid<Vec2Types>::subcell_coordinates[4];
371 template<> const FictitiousGrid<Vec3Types>::GridCoordinates FictitiousGrid<Vec3Types>::subcell_coordinates[8];
372 
373 template<> void FictitiousGrid<Vec2Types>::tag_intersected_cells ();
374 template<> void FictitiousGrid<Vec3Types>::tag_intersected_cells ();
375 
376 template<> void FictitiousGrid<Vec2Types>::subdivide_intersected_cells ();
377 template<> void FictitiousGrid<Vec3Types>::subdivide_intersected_cells ();
378 
379 extern template class FictitiousGrid<Vec2Types>;
380 extern template class FictitiousGrid<Vec3Types>;
381 
382 } // namespace SofaCaribou::topology
SofaCaribou::topology::FictitiousGrid::get_cell_element
CellElement get_cell_element(const CellIndex &sparse_cell_index) const
Get the element of a cell from its index in the sparse grid.
Definition: FictitiousGrid.h:192
SofaCaribou::topology::FictitiousGrid::number_of_nodes
UNSIGNED_INTEGER_TYPE number_of_nodes() const
Get the number of sparse nodes in the grid.
Definition: FictitiousGrid.h:139
SofaCaribou::topology::FictitiousGrid::Region
Definition: FictitiousGrid.h:110
SofaCaribou::topology::FictitiousGrid
Definition: FictitiousGrid.h:35
SofaCaribou::topology::FictitiousGrid::number_of_subdivisions
UNSIGNED_INTEGER_TYPE number_of_subdivisions() const
Get the number of subdivisions in the grid.
Definition: FictitiousGrid.h:145
SofaCaribou::topology::FictitiousGrid::get_node_indices_of
const SofaHexahedron & get_node_indices_of(const CellIndex &sparse_cell_index) const
Get the node indices of a cell from its index in the sparse grid.
Definition: FictitiousGrid.h:201
caribou::topology::Grid
Definition: Grid.h:21
SofaCaribou::topology::FictitiousGrid::Cell
A region is a cluster of cells sharing the same type and surrounded by either a boundary region or th...
Definition: FictitiousGrid.h:99
SofaCaribou::topology::FictitiousGrid::number_of_cells
UNSIGNED_INTEGER_TYPE number_of_cells() const
Get the number of sparse cells in the grid.
Definition: FictitiousGrid.h:133
SofaCaribou::topology::FictitiousGrid::CellData
The Cell structure contains the quadtree (resp. octree) data of a given cell or subcell.
Definition: FictitiousGrid.h:89