# Manifold Extraction
_Feel free to modify or add anything that you consider relevant._
The goal of this project is ... TODO
## 09/28/2023
(following from last week)
- [ ] Triangle test cases (Yifei)
- [ ] Adapt existing test code to Trimesh data structure
- [ ] Extract boundary
- [ ] Detect non-manifold singularities
- [ ] Visualization w/ existing vtu writer
- [ ] Component extract_subset
- [ ] Create `std::vector<Tuple>` for all cells with the tag
- [ ] Iterate over all cells with tag and store vertices in a `std::vector<Simplex>`
- [ ] Sort and remove duplicates from Simplex vector
- [ ] Create a map from `Simplex` to vector index (`int`)
- [ ] Create new tet connectivity
- options:
- "embedding_dimension"
- "subset_dimension"
## 09/21/2023
- [ ] Triangle test cases (Yifei)
- [x] move code to tests/component instead of src
- [x] Create dummy component, pr to man-ext in the fork
- [x] Find simply connected components
- [x] Use Trimesh Data structure
- [ ] Extract boundary
- [ ] Detect non-manifold singularies
- [ ] Visualization, existing components in toolkit?
- [ ] Code for identifying degenerate star domains (Michael)
- [ ] reread Attene's paper (again)
- [ ] look through new version of toolkit to see if any data structures/navigation modules there would be helpful
## Future TODOs
- [ ] Do similar things for Tet test cases
## Related Work
- [On converting sets of tetrahedra to combinatorial and PL manifolds](https://www.sciencedirect.com/science/article/pii/S0167839609000703?ref=cra_js_challenge&fr=RR-1)
- [Bijective Projection in a Shell](https://cims.nyu.edu/gcl/papers/2020-BijectivePrism.pdf) (contains quadratic programming problem for geometry side)
- [A scalable data structure for three-dimensional non-manifold objects](https://diglib.eg.org/handle/10.2312/SGP.SGP03.072-082)
## Attene's paper notes
### Definitions
The star of A in K, $S(A, K)$, is the sub-complex of $K$ made of all simplices of $K$ having $A$ as a face plus all their faces.
The link of A in K $L(A, K)$ is the set of simplices in $S(A, K)$ whose intersection with $A$ is empty.
An edge $e$ is singular if $L(e)$ is not connected.
A vertex $v$ is singular if $L(v)$'s boundary contains more than one component (is not connected).
### Algorithms
```
TF(T) = faces of tetrahedron (4)
FT(F) = tets incident at a face (1 or 2)
FE(F) = edges of a face (3)
EV(E) = vertices of an edge (2)
FV(F) = EV(FE(F)) = vertices of a face (3)
TV(T) = FV(TF(T)) = vertices of a tetrahedron (4)
TE(T) = FE(TF(T)) = edges of a tetrahedron (6)
CreateEdgeLinksAndStars(Tetrahedrization T ){
for each edge e in T
L(e) := new empty edge list()
T(e) := new empty tet list()
for each tet t in T
for each edge e in TE(t)
e2 := the edge in TE(t) sharing no vertex with e
Add e to L(e2) and t to T(e2)
}
//effectively creates a "ball" around each vertex, accessible by L(v)
CreateVertexLinks(Tetrahedrization T){
for each vertex v in T
L(v) := new empty face list
for each tet t in T
for each face f in TF(T)
v := the vertex of TV(t) which is not in FV(f)
Add f to L(v)
}
EditSingularVertex(Vertex v){
1. Look for a connected component in L(v) which is a combinatorial 2-ball
2. if there is such a component, let it be D
3. Compute the set T of tets incident at v and having a face in D
4. Create a new vertex w
5. Remove all the tets in T from the tetrahedrization
6. Create a new tet {w, w^i_1, w^i_2, w^i_3} for each face {w^i_1, w^i_2, w^i_3} in D
7. Remove D from L(v)
8. If L(v) has more than one component go to 1, else go to 15
9. else (i.e. if there are no combinatorial 2-balls in L(v))
10. Extract a boundary loop B of L(v)
11. Compute the set D of faces incident at v and having an edge in B
12. Create a new vertex w
13. Create a new tet {w, w^i_1, w^i_2, v} for each face {w^i_1, w^i_2, v} in D
14. Add all the faces {w, w^i_1, w^i_2} to L(v)
15. If L(v) has more than one boundary component go to 10, else terminate
}
```
## Things to implement
```
CountConnectedComponents(Graph G){
count = 0
for v in G.Vertices:
if v is unmarked:
mark v
count++
unvisitedAdj = v.adj
i = 0
while i != len(unvisitedAdj):
mark unvisitedAdj[i]
append unvisitedAdj[i].adj to unvisitedAdj
i++
return count
}
DetectSingularEdges(Edges E){
SingularEdges = []
for e in E:
if len(ConnectedComponents(L(e))) > 1:
add e to SingularEdges
}
DetectSingularVertices(Vertices V){
SingularVertices = []
for v in V:
if len(ConnectedComponents(boundary(L(v)))) > 1:
add e to SingularVertices
}
EditSingularEdge(Edge e){
}
```
Notes from Nov 2
init everything as -1
every corner of every tri, get new id from counter, assign id to all corners in the connected component of this chosen corner
for every tri:
for every corner:
if its id != -1 continue;
else, get id from a counter
assign this id to all corners in the connect component of this chosen vertex.
```
reTopologize2D(Triangulation T){
counter = 0
for t in T:
for v in V(T):
}
```