mlivesu / cinolib

A generic programming header only C++ library for processing polygonal and polyhedral meshes

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

information

untereiner opened this issue · comments

Hello,
This repository was suggested to me by github and I just read the readme.
Looking at your research oriented list of mesh libraries, I wanted to suggest you CGOGN_2 and CGoGN_3 as "unified data structure for multiple dimension handling".
In fact, these libraries implement a mesh data structure (based on a theoretical model) that can handle 0D, 1D, 2D and 3D oriented open or closed manifolds whatever their discretization (polygons or polyhedrons). There is also a cgal package based on the same theoretical data model that can handle nD objects. A while ago we made some benchmarks also.

Hi, thanks for the pointers. Are these data structures restricted to oriented manifolds only? In many practical cases I'd like to deal with non manifold topological spaces as well

I just checked, here is the beginning of a data structure implementing chain of maps that represent non manifold objects. I think there will be a 2d and 3d implementation.

There is also an implementation for non oriented manifolds with generalized maps in 1d, 2d, and 3d here

Thanks again for the pointers :)
I would seriously consider combinatorial maps if I were to rewrite cinolib from scratch or to undergo a major refactoring of the library*. However, I was never able to fully understand whether I could design a generalized combinatorial map that operates on multiple dimensions at once. I mean, I know that combinatorial maps extend to any dimension, but it seems to me that the dimension must be fixed a priori, hence if I want to process surface and volume data I'd need two disjoint data structures, which is not what I want. The feature that I like the most in Cinolib is that I can write most of the algorithms without even thinking whether they are going to be executed on a surface or a volume mesh, because the code is just the same in both cases. This is much more than having a data structure that extends to any dimension...
Of course there is some efficiency tradeoff to pay for this generality, but this feature comes really handy to me and completely erases code duplication.
So, I am asking you because you seem to be an expert in combinatorial maps: do you think a similar feature could be implemented also with such a data structure? If so, we should meet at some point :)

*: not likely to happen though. Too much time needed and no serious reward to go through this pain

However, I was never able to fully understand whether I could design a generalized combinatorial map that operates on multiple dimensions at once.

Of course you can! And it is effortless. There are two things to know:

  1. The construction of a cmap (generalized or combinatorial): You can build a library with classes for cmaps of each dimensions (like in CGoGN: CMap2, CMap3, etc). You can also design a data structure with compile time dimension (ex in cgal). You can also design a data structure that allows to add arrays to store involutions at execution time. Trade off, as usual
  2. The browsing of a cmap. Per definition a cmap of dimension N is an assemblage of all the cells from dimension 0 to N-1. So yes you can browse 2d cells in a 3d cmap. All the magic comes from the foreach_xxx functions. For example this one one allows to brows all edges incident to vertex of dimension 2 (like in CMap2) in a 3d CMap.

The advantage is that all incidences and adjacencies are defined in every dimension. They come for free from the model. Since the model is well defined with the relations between the darts you even don't need unit tests...

Here you have dimensionless algorithms. The foreach_incident_vertex and Vertex cell are defined for each dimension you can call this function on a CMap2 or CMap3 (even a CMap4 with good arithmetic operations) without any trouble.

I am open to discussion :)

That's not exactly what I meant. In many practical cases when you implement an algorithm there are "semantically identical" operations require iterating over elements with different dimensionality, depending on whether you have a volume or a surface mesh. Here is a practical example: suppose you want to implement a simple flood fill algorithm that starts from a mesh seed and iteratively expands to adjacent elements. In the case of a surface mesh, you'd start from a triangle and iteratively expand on the unvisited edge-adjacent triangles. In the case of a volume mesh, you'd start from a tetrahedron and iteratively expand on the unvisited face-adjacent tetrahedra. Maybe having a generalized floodfill algorithm is not super exciting, but in my experience similar things also happen in many other cases. In cinolib I play a lot with name conventions, so that a poly is a polygon in a surface mesh and a polyhedron in a volume mesh. I guess in combinatorial maps one could similarly "mix" iterators with different dimensionalities

haa I get it now. These kind of algorithms are not implemented (if I am correct) in these libraries. But it is still possible using the "low level API" . These libraries are written with the extensive versions of iterators (foreach_cell, foreach_incident_xxxx, foreach_adjacent_xxxx_trough_yyyy). But it is possible to get the n - 1 cell dimension type from a map of dimension n.
The generic foreach_incident_cell function is not written yet but is not difficult based on what is already written. All these functions are intensively using foreach_dart_of_orbit functions

You could have adjacencies and mix dimensions like for the floodfill algorithm.
It would give you something like this skeleton

template <typename MAP>
flood(MAP& map)
{
     using CellTypeOuter = cell_type(mesh_traits<MAP>::dimension );
     using CellTypeIner = cell_type(mesh_traits<MAP>::dimension - 1 );
      
      //iterate over all faces in 2d or volumes in 3d depending on the type MAP
      foreach_cell(map,  [&](CellTypeOuter c) -> bool {
            //given the type of the top cell c (face or volume) 
           //iterate over all adjacent dim - 1 cells (edges in 2d or faces in 3d)
            foreach_adjacent_cell<CellTypeIner>(map, c,  [&](CellTypeOuter av) -> bool {
                   //do something with av
           });
      });

}

This is interesting! Thanks

I have updated the readme to acknowledge your data structures and their capabilities. I am looking forward to play with combinatorial maps in the way I mentioned in my previous messages. I am closing the issue here. Thanks