plexus icon indicating copy to clipboard operation
plexus copied to clipboard

Expose mutations for removing topology in views.

Open olson-sean-k opened this issue 6 years ago • 4 comments

Currently, the mutation API is strictly internal and is not accessible to user code. It is also the only API that directly exposes basic topological operations, including removals. As this API matures, I've considered exposing it directly to enable more advanced usage of Plexus, but I'd like to expose most necessary operations directly via views using a topologically sound API that avoids low-level operations.

At the moment, views do not expose any operations resulting in a net loss of topological structures and provide no direct removal operations. It's not too clear to me how best to accomplish this, but views should expose some way to remove topology! This is deceptively complex. For example, what exactly should happen if a half-edge is removed? When should a removal affect other topological structures? For example, when a face is removed, should only the face be removed, or also its edges and vertices? How does topology collapse or recompose?

olson-sean-k avatar Aug 28 '18 07:08 olson-sean-k

Have you looked at OpenMesh and He_Mesh? They both use the half edge data structure and could serve as inspiration for this.

virtualritz avatar Sep 04 '18 02:09 virtualritz

So far, I'm experimenting with a simple hierarchical model for removals. When topology is removed, any and all dependent topology is also removed. This means that removing faces is the least destructive and removing vertices is the most destructive; no topology depends on faces, but all other topology depends on vertices (transiently or otherwise).

Some such removals have been implemented in views by 8cc191c and 38c0a88. Additionally, certain operations also result in removals and often compose a removal with insertions, such as collapsing edges or joining adjacent faces over an edge.

This differs from OpenMesh, which allows topology to be removed individually. I'd like to avoid that model, because it can easily leave a graph in an inconsistent state and one of the design goals of Plexus is to avoid that kind of API. (This is not entirely out of the question; there's a chance that the internal mutation API, which behaves this way, may be exposed.)

This can be more cumbersome, but should ultimately allow for the same mutations. OpenMesh provides a simple example that removes topology from a cube.

In this example we delete all faces except one and the corresponding vertices.

That may look something like this in Plexus:

let mut graph = Cube::new()
    .polygons_with_position_from(Bounds::unit_radius())
    .collect_with_indexer::<MeshGraph<Point3<f64>>, _>(HashIndexer::default())?;
// Preserve the target face "abc".
let abc = graph.faces().nth(0).unwrap().key();
let (x, y) = {
    // Traverse from the target face to its opposite face.
    let face = graph
        .face(abc)
        .unwrap()
        .into_arc()
        .into_opposite_arc()
        .into_next_arc()
        .into_next_arc()
        .into_opposite_arc()
        .into_face()
        .expect("cube");
    // Traverse the opposite face to opposing vertices.
    let mut vertices = face.vertices().map(|vertex| vertex.key()).step_by(2);
    (
        vertices.next().expect("cube"),
        vertices.next().expect("cube"),
    )
};
// Remove the vertices (along with their associated edges and faces).
graph.vertex_mut(x).unwrap().remove()?;
graph.vertex_mut(y).expect("cube").remove()?;

olson-sean-k avatar Jan 30 '19 21:01 olson-sean-k

This differs from OpenMesh, which allows topology to be removed individually.

Hmm, that's not quite right. In the linked example, removing vertices in OpenMesh implicitly removes their associated edges. Only faces are removed beforehand.

olson-sean-k avatar Jan 30 '19 22:01 olson-sean-k

This is nearly fixed; only vertex removal is yet unimplemented and there is a remaining bug in arc removals. Removals are destructive, and will always remove any dependent topology.

There are still some related questions to be answered though. For example, should disjoint vertices be allowed? I've so far designed around the idea that they should not. Disjoint vertices seem degenerate in a directed graph. If this is not allowed, then topological dependencies become a bit more complicated. Still, I think this will lead to a workable design. Hopefully this issue can be closed soon. :-)

olson-sean-k avatar Feb 27 '19 01:02 olson-sean-k