---
# System prepended metadata

title: Manifold Extraction

---


# 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):
            
}
```