Meshes.jl icon indicating copy to clipboard operation
Meshes.jl copied to clipboard

Cleaning and repairing meshes

Open juliohm opened this issue 3 years ago • 17 comments

In #353 some cleaning functions were proposed to eliminate vertices of a mesh that are orphan or to "merge" them somehow. Instead of providing this functionality as isolated functions, we should aim for a more composable transform interface.

I propose that we start listing the possible cleaning operations that we would like to implement in this issue, and then we can open separate PRs for each of them. A good list of cleaning operations is available in the MeshLab project as discussed in our Zulip channel.

  • [x] 0 = only duplicated vertices and faces are removed
  • [x] 1 = remove unreferenced vertices
  • [ ] 2 = remove non-manifold faces
  • [ ] 3 = remove degenerate faces
  • [ ] 4 = remove non-manifold vertices
  • [ ] 5 = split non-manifold vertices by threshold
  • [ ] 6 = merge close vertices (given a radius)
  • [x] 7 = coherently orient faces

juliohm avatar Dec 25 '22 10:12 juliohm

I believe MeshLab has the same cleaning operations than the R package Rvcg.

I already implemented 0 (I called it gather(mesh)) and 1. I don't know what is a manifold vertex/face. 6 can be obtained by a minor modification of 0. For 7 I don't know how to do.

stla avatar Dec 25 '22 13:12 stla

I don't know what is a manifold vertex/face

https://sinestesia.co/blog/tutorials/non-manifold-meshes-and-how-to-fix-them/

Basically, a mesh is said to be manifold when it represents a "simple" surface, i.e. when you look at it locally you can imagine a Cartesian plane with two dimensions. When a vertex shares more than 3 edges or when an edge shares more than 2 faces, it means that we have some sort of feature that doesn't belong to the "surface", e.g. a face that is hanging in a T shape.

juliohm avatar Dec 25 '22 21:12 juliohm

Thanks. Regarding the names for these functions, in Rvcg there's a unique function named vcgClean. The wanted operations are given by one or more numbers between 0 and 7. Personally I don't really like.

stla avatar Dec 26 '22 08:12 stla

Yes, I think we can aim for a more composable set of transforms. The naming will be difficult but we can certainly do better.

juliohm avatar Dec 26 '22 09:12 juliohm

Hello, I have a function which removes the unused vertices of a mesh. How should I name it and where should I put it if I want to do a PR? Currently it is named removeUnusedVertices. This function is necessary for the clipping (another function I have).

stla avatar Apr 24 '23 07:04 stla

Let's follow the numbering convention in MeshLab and Rvcg that you shared in https://github.com/JuliaGeometry/Meshes.jl/issues/354#issuecomment-1364685494.

We can create a single transform called Repair{K} that takes a code K as a static parameter and dispatches the correct algorithm. For example:

"""
    Repair{K}

Perform repairing operation with code `K`.

## Available operations

- K = 0: duplicated vertices and faces are removed
- K = 1: ...
"""
struct Repair{K} <: StatelessGeometricTransform end

# implement operation K = 0
function apply(transform::Repair{0}, mesh)
  # TODO
end

You can save this transform in our transforms folder along with the other available geometric transforms.

juliohm avatar Apr 24 '23 10:04 juliohm

Hmm I don't understand this code. Could you show me how to call Repair{0}? I mean if I have a mesh, how to apply Repair{0} to this mesh?

stla avatar Apr 26 '23 11:04 stla

Any transform defined in this package can be applied as a functor, so you can mesh |> Repair{0} |> Repair{1} for example. You can also construct a lazy pipeline to apply to any new mesh you get, this is done with the \to operator:

pipe = Repair{0} → Repair{1}

# pipe syntax
mesh |> pipe

# functor syntax
pipe(mesh)

juliohm avatar Apr 26 '23 12:04 juliohm

I've done the job. But I tried mesh |> Repair{1} and that does not work (no method matching).

stla avatar Apr 28 '23 13:04 stla

Should I export Repair{1}? I exported Repair.

stla avatar Apr 28 '23 13:04 stla

Can you share your attempt in a PR so that we can review it together? The transform machinery has many fallback implementations and so you need to implement the correct method to get it dispatched correctly.

juliohm avatar Apr 28 '23 13:04 juliohm

@stla I will work on Repair{7}, we already have it implemented because our HalfEdgeTopology constructor reorders the vertices to make the resulting set of faces coherent.

juliohm avatar Apr 29 '23 13:04 juliohm

@stla I added Repair{7}. You mentioned that you already have Repair{0} and Repair{6} implemented right? Mind submitting them as PRs? I've created a check list in this issue so that we track the missing ones.

juliohm avatar Apr 29 '23 14:04 juliohm

@juliohm I have 0 only for removing the duplicated vertices, not the duplicated faces. Then 6 is very similar, it suffices to replace the equality with the closeness.

stla avatar Apr 29 '23 15:04 stla

@juliohm Now we have everything ready for the clipping. Should we define clip(mesh) as a transform too?

stla avatar Apr 30 '23 02:04 stla

Can you remind what the clip function does exactly? Maybe in a separate issue or Zulip? This issue we are using to track the repairing operations.

juliohm avatar Apr 30 '23 02:04 juliohm